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 494217b  pr-management-triage: ask author before promoting 
unresolved-thread PRs (#175)
494217b is described below

commit 494217b9080e3649a68c544ffe19d14d45491a51
Author: Yeonguk Choo <[email protected]>
AuthorDate: Sun May 17 01:50:55 2026 +0900

    pr-management-triage: ask author before promoting unresolved-thread PRs 
(#175)
---
 .claude/skills/pr-management-stats/render.md       |   4 +-
 .claude/skills/pr-management-triage/SKILL.md       |  48 ++++--
 .claude/skills/pr-management-triage/actions.md     | 120 ++++++++-------
 .../pr-management-triage/classify-and-act.md       |  61 +++++++-
 .../pr-management-triage/comment-templates.md      |  83 ++++++----
 .../pr-management-triage/interaction-loop.md       |  38 +++--
 .claude/skills/pr-management-triage/rationale.md   | 168 ++++++++++++++++++---
 .../skills/pr-management-triage/stale-sweeps.md    |  89 ++++++++++-
 .../pr-management-triage-comment-templates.md      |  17 ++-
 9 files changed, 480 insertions(+), 148 deletions(-)

diff --git a/.claude/skills/pr-management-stats/render.md 
b/.claude/skills/pr-management-stats/render.md
index 3a5ecb2..7956461 100644
--- a/.claude/skills/pr-management-stats/render.md
+++ b/.claude/skills/pr-management-stats/render.md
@@ -188,7 +188,7 @@ The "What needs attention" panel is built from this fixed 
rule set, evaluated in
 | 3 | `len(stale_triaged_drafts) > 0` (drafts triaged ≥ 7d ago, no reply) | 
medium | 🗑️ | `Close <N> stale-triaged drafts (≥7d, no response)` | Closure 
path lives under the `stale` flow (sweep step 1a). | `/pr-management-triage 
stale` |
 | 4 | `len(ready_open) >= 50` | high | 📥 | `<N> PRs labeled "ready for 
maintainer review"` | The `ready for maintainer review` queue is past the 
triage stage; it needs maintainer review attention, not triage. | 
`/pr-management-code-review ready` |
 | 5 | `20 <= len(ready_open) < 50` | medium | 📥 | `<N> PRs in "ready for 
maintainer review" queue` | Same trigger family as rule 4 — banded by queue 
size so the priority drops once the queue is comfortable. | 
`/pr-management-code-review ready` |
-| 6 | `len(responded_no_ready) > 0` (triaged + responded but not 
ready-for-review) | medium | 🔄 | `<N> triaged PRs have author responses 
awaiting re-triage` | These will surface as mark-ready-with-ping inside the 
regular triage sweep. | `/pr-management-triage all PR issues` |
+| 6 | `len(responded_no_ready) > 0` (triaged + responded but not 
ready-for-review) | medium | 🔄 | `<N> triaged PRs have author responses 
awaiting re-triage` | These will surface as request-author-confirmation (first 
leg of the two-sweep mark-ready gate) inside the regular triage sweep. | 
`/pr-management-triage all PR issues` |
 | 7 | top area's `untriaged_4w + untriaged_1_4w >= 5` | medium | 📍 | `Area 
"<area>" has <total> contributor PRs (<X> untriaged >4w)` | One area is 
dominating the untriaged queue; scoping a triage pass to it clears the bulk of 
the load. | `/pr-management-triage label:area:<area>` |
 | 8 | `velocity_drop > 30` (last_wk total - this_wk total) | low | 📉 | `PR 
closure velocity dropped <N> this week` | No immediate action — re-check next 
week to see if the drop persists or was a one-off. | — |
 | 9 | top ready-trend area's growth in last 7d ≥ 10 PRs | low | 📈 | 
`Ready-for-review queue in "<area>" grew by <N> this week` | Growth 
concentrated in one area suggests it'd benefit from a focused review pass. | 
`/pr-management-code-review label:area:<area>` |
@@ -248,7 +248,7 @@ Distinct from the colour scheme: these are the four 
conceptual *states* a contri
 | Marker | Definition | Colour | Maintainer action |
 |---|---|---|---|
 | `Ready for review` | `ready for maintainer review` label is present | green 
| run `/maintainer-review` to actually code-review the PR |
-| `Responded` | PR is triaged AND author has commented or pushed after the 
triage comment, AND not yet `Ready` | bright cyan | re-triage; may now qualify 
for `mark-ready-with-ping` |
+| `Responded` | PR is triaged AND author has commented or pushed after the 
triage comment, AND not yet `Ready` | bright cyan | re-triage; may now qualify 
for `request-author-confirmation` (first leg of the two-sweep mark-ready gate) |
 | `Waiting for Author` | PR is triaged, no author response — OR — PR is a 
draft (whether triaged or not) | amber | nothing; author owns the next move 
(may become a sweep candidate after 7d) |
 | `Not yet triaged` | None of the above. Non-draft PR that has never received 
a quality-criteria comment | blue (or grey) | run `/pr-management-triage` to 
give it a first look |
 
diff --git a/.claude/skills/pr-management-triage/SKILL.md 
b/.claude/skills/pr-management-triage/SKILL.md
index afe15c8..c6c59e3 100644
--- a/.claude/skills/pr-management-triage/SKILL.md
+++ b/.claude/skills/pr-management-triage/SKILL.md
@@ -7,9 +7,10 @@ description: |
   propose a disposition, and — on the maintainer's
   confirmation — carry out the action via `gh`. Disposition
   options per PR: draft / comment / close / rebase / CI-rerun
-  / workflow-approve / ping-stale-reviewer / mark `ready for
-  maintainer review`. Does **not** perform code review — that
-  lives in `pr-management-code-review`.
+  / 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`.
 when_to_use: |
   Invoke when a maintainer says "triage the PR queue", "go
   through new contributor PRs", "run the morning triage",
@@ -148,10 +149,17 @@ bot checks (`Mergeable`, `WIP`, `DCO`, `boring-cyborg`) 
while
 `Tests`, `CodeQL`, and newsfragment-check sit in
 `action_required`; trusting the rollup there fills the
 maintainer-review queue with PRs whose real CI never ran. The
-guard applies identically to the
-[`mark-ready-with-ping`](actions.md#mark-ready-with-ping--promote-a-likely-addressed-pr--ping-reviewers)
-action — any code path that adds the `ready for maintainer
-review` label runs the REST check first.
+guard applies identically to every code path that adds the
+`ready for maintainer review` label, including the
+[`mark-ready`](actions.md#mark-ready--add-ready-for-maintainer-review-label)
+action invoked from
+[row 14a](classify-and-act.md#decision-table) after author
+confirmation. The
+[`request-author-confirmation`](actions.md#request-author-confirmation--ask-the-pr-author-whether-feedback-is-addressed)
+action itself does not add the label (it only posts a comment),
+so the REST check is not required there — but the subsequent
+sweep that promotes the PR via `mark-ready` runs the check
+exactly as documented above.
 Implementation recipe: [`actions.md#mark-ready`](actions.md).
 
 **Golden rule 2 — propose in groups, fall back to per-PR.** The
@@ -379,14 +387,20 @@ the order:
 3. `deterministic_flag` with actions `draft` / `comment` /
    `rebase` / `rerun` / `ping` — in that order
 4. `stale_review` → `ping`
-5. `deterministic_flag` → `mark-ready-with-ping` (label-bearing
-   group, presented just before plain `mark-ready` so the
-   maintainer reviews all label-add proposals back-to-back)
-6. `passing` → `mark-ready`
-7. Stale sweeps (`stale_draft` → `close`, `inactive_open` →
+5. `deterministic_flag` → `request-author-confirmation`
+   (engagement heuristic fired; ask the author whether the
+   PR is ready before any label or reviewer-ping is generated
+   — first leg of the two-sweep gate)
+6. `author_confirmed_ready` → `mark-ready` (author replied
+   to a prior request; silent label apply, presented just
+   before plain `mark-ready` so the maintainer reviews all
+   label-add proposals back-to-back)
+7. `passing` → `mark-ready`
+8. Stale sweeps (`stale_draft` → `close`, `inactive_open` →
    `draft`, `stale_workflow_approval` → `draft`,
    `stale_ready_label` → `strip-ready-label`,
-   `stale_ready_label_unhealthy` → `close`)
+   `stale_ready_label_unhealthy` → `close`,
+   `stale_author_confirm_request` → `ping`)
 
 For each group, present one screen worth of headline info
 (PR number, title, author, 1-line reason, label chips) and
@@ -447,6 +461,10 @@ When the maintainer has worked through every interactive 
group
   strip the label (4a — branch healthy) or propose `close`
   (4b — red CI or merge conflicts). See
   
[`stale-sweeps.md#sweep-4--stale-ready-for-review-label`](stale-sweeps.md#sweep-4--stale-ready-for-review-label).
+- on PRs holding a pending author-confirmation request
+  (first leg of row 14c) whose author has been silent ≥ 7
+  days, propose plain `ping` to escalate. See
+  
[`stale-sweeps.md#sweep-5--stale-author-confirm-request`](stale-sweeps.md#sweep-5--stale-author-confirm-request).
 
 Each sweep emits its own group in the interaction loop (Step 3),
 so the maintainer still confirms before any PR is touched.
@@ -461,8 +479,8 @@ excludes labeled PRs) — see
 On exit, print a one-screen summary:
 
 - counts of PRs handled per action (drafted, commented, closed,
-  rebased, reruns triggered, marked ready, pinged, workflow
-  approvals, suspicious flags)
+  rebased, reruns triggered, author-confirm requests posted,
+  marked ready, 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 23c4f1a..864d2a7 100644
--- a/.claude/skills/pr-management-triage/actions.md
+++ b/.claude/skills/pr-management-triage/actions.md
@@ -220,78 +220,84 @@ error; this is the only action of the skill whose sole 
purpose
 
 ---
 
-## `mark-ready-with-ping` — promote a likely-addressed PR + ping reviewers
+## `request-author-confirmation` — ask the PR author whether feedback is 
addressed
 
-A composite of `mark-ready` plus a `ping` comment. Used when
-the only `deterministic_flag` signal is unresolved review
-threads **and** the
+Single mutation. Used when the only `deterministic_flag` signal
+is unresolved review threads **and** the
 
[`unresolved_threads_only_likely_addressed`](classify-and-act.md#unresolved_threads_only_likely_addressed)
 sub-flag is true (the author has engaged with every unresolved
 thread via a post-comment commit or an in-thread reply).
 
-**Same mandatory pre-mutation guard as `mark-ready`.** Run
-the `action_required` REST check first and refuse — by
-reclassifying as `pending_workflow_approval` — if any workflow
-run is awaiting approval. The reasoning in the
-[`mark-ready`](#mark-ready--add-ready-for-maintainer-review-label)
-section above applies identically here.
-
-Order of operations: **post the comment first, then add the
-label.** The comment names the reviewers and asks them to
-re-look at the threads; the label then routes the PR into the
-review queue. If the label is added first, the reviewers see a
-"ready for maintainer review" notification before the comment
-that explains *why* it was promoted, which reads as the bot
-mark-ready'ing without context.
+The action does **not** add the `ready for maintainer review`
+label and does **not** `@`-mention the original reviewers.
+Those steps belong to the second leg of this two-sweep flow,
+gated on an explicit author confirmation
+([row 14a](classify-and-act.md#decision-table) →
+[`mark-ready`](#mark-ready--add-ready-for-maintainer-review-label)).
 
 ```bash
-# 1. Pre-check: refuse if any workflow run is awaiting approval (same as 
mark-ready).
-#    Runs awaiting approval surface as `status: "completed"` +
-#    `conclusion: "action_required"` — `?status=action_required` matches
-#    none of them, so post-filter on `conclusion`.
-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 mark-ready-with-ping: <N> has ${pending} workflow run(s) 
awaiting approval at ${head_sha}" >&2
-  # Reclassify: this PR is really pending_workflow_approval.
-  exit 2
-fi
-
-# 2. Post the ping comment (mark-ready-with-ping template).
-gh pr comment <N> --repo <repo> --body-file /tmp/pr-<N>-mark-ready-with-ping.md
-
-# 3. Apply the label.
-gh pr edit <N> --repo <repo> --add-label "ready for maintainer review"
+gh pr comment <N> --repo <repo> --body-file 
/tmp/pr-<N>-request-author-confirmation.md
 ```
 
 Body template:
-[`comment-templates.md#mark-ready-with-ping`](comment-templates.md).
-
-The body must `@`-mention every reviewer whose unresolved
-thread we believe was addressed (so they get the notification)
-and `@`-mention the PR author once at the top (so the
-contributor sees the rationale). The list of reviewers comes
-from the unresolved-thread reviewers captured during
-classification.
+[`comment-templates.md#request-author-confirmation`](comment-templates.md).
+
+The body `@`-mentions the PR author only, and **must** include
+the canonical marker string `ready for maintainer review
+confirmation` verbatim — that string is what
+[`viewer_confirmation_request_present`](classify-and-act.md#viewer_confirmation_request_present)
+searches for on subsequent sweeps to detect that a confirmation
+request is in flight. Do not paraphrase the marker.
+
+### Why no label, no reviewer mention
+
+The classifier's signal that fired this action is *engagement*
+(post-review commits, in-thread author replies), not
+*resolution*. A post-review commit does not guarantee the
+commit addresses the specific thread; an in-thread reply does
+not guarantee the reply resolves it. Adding the label and
+mentioning reviewers off the engagement signal alone pushes a
+notification framed as a stronger claim than the underlying
+evidence supports. The two-sweep gate — ask the author, wait
+for their reply, then promote — moves the resolution check to
+the only person who reliably knows: the author.
+
+The label is also intentionally absent at this stage so that
+the PR does not enter the maintainer review queue until after
+the author has confirmed. Reviewers are reached via the queue,
+not via direct `@`-mention from the bot — see
+[`rationale.md`](rationale.md) for the longer argument.
+
+### What happens next
+
+- Author replies → next sweep classifies the PR as
+  
[`author_confirmation_received`](classify-and-act.md#author_confirmation_received)
+  and proposes 
[`mark-ready`](#mark-ready--add-ready-for-maintainer-review-label).
+  The triaging maintainer reads the author's reply alongside
+  the proposal and confirms (or overrides to `skip` / `ping`
+  if the reply is non-affirmative).
+- Author silent → on the cooldown sweep, the PR matches the
+  [stale author-confirm-request 
sweep](stale-sweeps.md#sweep-5--stale-author-confirm-request),
+  which proposes a plain `ping` (or `skip`).
+- Author pushes a new commit before replying → the
+  
[`viewer_confirmation_request_present`](classify-and-act.md#viewer_confirmation_request_present)
+  precondition fails (the confirmation request now predates the
+  new head commit) and the PR drops back to row 14c / 15 for
+  re-classification against the new state.
 
-If the label step fails after the comment is already posted,
-**do not retry the comment** — surface the label-add error
-to the maintainer and let them apply the label manually. A
-duplicate ping comment is the worse of the two failure modes.
+### Failure handling
 
-If the comment step fails (network blip, rate-limit), do not
-proceed to the label — the maintainer would then see a PR
-labelled `ready for maintainer review` with no explanation of
-how it got there.
+A failed `gh pr comment` (network blip, rate-limit) is non-
+destructive — surface the error and let the maintainer retry on
+the next sweep. No partial state to clean up.
 
 ### Falling back to plain `ping`
 
 If the post-confirmation drill-in (e.g. the maintainer pulled
-the PR out of the group with `[P]ick`) reveals that the
-threads are *not* actually addressed, the maintainer can
-override the action to `ping`. The override drops the label
-step entirely and posts the regular
+the PR out of the group with `[P]ick`) reveals that the threads
+are *not* actually addressed (the author's engagement was a
+clarifying question or a partial fix), the maintainer can
+override the action to `ping`. The override posts the regular
 [`reviewer-ping`](comment-templates.md#reviewer-ping) body
 instead. See
 [`interaction-loop.md#group-action-override`](interaction-loop.md).
@@ -597,7 +603,7 @@ For every action that includes a comment, post the comment
 | `close` | post comment → close → label |
 | `flag-suspicious` | post comment → close → label *(per PR in the batch)* |
 | `mark-ready` | label only |
-| `mark-ready-with-ping` | post comment → label |
+| `request-author-confirmation` | post comment only (no label) |
 | `strip-ready-label` | remove-label only (no comment) |
 | `rerun` | rerun (no comment) |
 | `rebase` | update-branch (no comment) |
diff --git a/.claude/skills/pr-management-triage/classify-and-act.md 
b/.claude/skills/pr-management-triage/classify-and-act.md
index 3fa7040..f96f809 100644
--- a/.claude/skills/pr-management-triage/classify-and-act.md
+++ b/.claude/skills/pr-management-triage/classify-and-act.md
@@ -45,7 +45,7 @@ filter is skipped silently from the main triage flow.
 | F2 | Author is a known bot | login is `dependabot`, `dependabot[bot]`, 
`renovate[bot]`, `github-actions`, `github-actions[bot]`, or matches `*[bot]` |
 | 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 [...]
+| 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 [...]
 | F5b | Maintainer-to-maintainer ping unanswered | Most recent collaborator 
comment from the **union** described in F5a above `@`-mentions one or more 
logins other than the PR author AND none of those mentioned logins have posted 
on the PR (general comments **or** review threads) or in `latestReviews` after 
that comment. Team mentions (e.g. `@<upstream>-committers`) are conservatively 
treated as F5b matches. |
 | F6 | Maintainer co-drafted | `isDraft == true` AND any of: (a) 
`latestReviews` has a node with `authorAssociation ∈ {OWNER, MEMBER, 
COLLABORATOR}` AND `author.login ≠ <viewer>` AND `state ∈ {COMMENTED, 
CHANGES_REQUESTED, APPROVED}` AND `submittedAt > commits(last:1).committedDate` 
AND review body is non-empty (avoids the "review with only inline thread 
comments and an empty top-level body" false positive — those are already 
counted by row 14/15 unresolved-thread logic); (b) `comments(l [...]
 
@@ -85,7 +85,9 @@ Action verbs are defined in [`actions.md`](actions.md).
 | 11 | [`ci_failures_only`](#ci_failures_only) AND any failure ∈ 
`recent_main_failures`               | `deterministic_flag`       | `rerun`     
           | K/N CI failures match recent main-branch PRs — likely systemic |
 | 12 | [`ci_failures_only`](#ci_failures_only) AND every failed check is a 
[static check](#static_check) | `deterministic_flag`     | `comment`            
  | Only static-check failures — needs a code fix, not a rerun |
 | 13 | [`ci_failures_only`](#ci_failures_only) AND `failed_count <= 2` AND 
`commits_behind <= 50`     | `deterministic_flag`       | `rerun`               
 | N CI failure(s) on otherwise clean PR — likely flaky, suggest rerun |
-| 14 | [`unresolved_threads_only`](#unresolved_threads_only) AND 
[`unresolved_threads_only_likely_addressed`](#unresolved_threads_only_likely_addressed)
 | `deterministic_flag` | `mark-ready-with-ping` | K unresolved thread(s) from 
<reviewers> appear addressed (post-review commits / in-thread author replies) — 
promote to ready and ping reviewers to confirm |
+| 14a | [`author_confirmation_received`](#author_confirmation_received)        
                        | `author_confirmed_ready`   | `mark-ready`           | 
Author confirmed PR is ready for maintainer review — apply label |
+| 14b | [`pending_author_confirmation`](#pending_author_confirmation)          
                        | `awaiting_author_confirmation` | `skip`             | 
Awaiting author confirmation requested M days ago |
+| 14c | [`unresolved_threads_only`](#unresolved_threads_only) AND 
[`unresolved_threads_only_likely_addressed`](#unresolved_threads_only_likely_addressed)
 | `deterministic_flag` | `request-author-confirmation` | K unresolved 
thread(s) from <reviewers> show author engagement — ask author to confirm 
readiness for maintainer review |
 | 15 | [`unresolved_threads_only`](#unresolved_threads_only)                   
                       | `deterministic_flag`       | `ping`                 | 
K unresolved review thread(s) from <reviewers> — ping author + reviewers |
 | 16 | No real CI ran (see [Real-CI guard](#real-ci-guard)) AND `mergeable != 
CONFLICTING` AND author NOT first-time | `deterministic_flag` | `rebase`        
    | No real CI checks triggered, branch mergeable — rebase to re-trigger |
 | 17 | [`has_deterministic_signal`](#has_deterministic_signal) (fallback)      
                       | `deterministic_flag`       | `draft`                | 
Has quality issues — convert to draft with violations comment |
@@ -226,6 +228,61 @@ All of:
 Heuristic, conservative on purpose. Rationale:
 
[`rationale.md#unresolved_threads_only_likely_addressed-heuristic-detail`](rationale.md#unresolved_threads_only_likely_addressed-heuristic-detail).
 
+### `viewer_confirmation_request_present`
+
+True when the viewer (the authenticated maintainer running the
+skill) has posted a comment on the PR whose body contains the
+literal marker string
+
+> `ready for maintainer review confirmation`
+
+(the canonical marker baked into the `request-author-confirmation`
+template — see
+[`comment-templates.md#request-author-confirmation`](comment-templates.md))
+AND that comment's `createdAt` is **after** the PR's head
+`committedDate`. The post-last-commit check means a fresh
+contributor push invalidates the prior confirmation request
+(new code = new threads possibly opened, our previous question
+no longer applies).
+
+Marker matching is a case-sensitive substring search on the
+comment body. The marker text is fixed in the framework template
+to make this glossary entry deterministic; adopters customising
+the wording of the rest of the body must keep this exact string
+verbatim — the same contract as the
+[`Pull Request quality criteria`](#decision-table) link text
+for `already_triaged` (rows 3–4).
+
+### `pending_author_confirmation`
+
+[`viewer_confirmation_request_present`](#viewer_confirmation_request_present)
+is true AND there is **no** comment by the PR author (issue-level
+in `comments(last:10)` **or** review-thread reply in
+`reviewThreads.nodes.comments`) with `createdAt` greater than
+the confirmation-request comment's `createdAt`.
+
+The PR is mid-cycle: we have asked, the author has not yet
+answered.
+
+### `author_confirmation_received`
+
+[`viewer_confirmation_request_present`](#viewer_confirmation_request_present)
+is true AND there **is** a comment by the PR author (issue-level
+or review-thread reply, as in
+[`pending_author_confirmation`](#pending_author_confirmation))
+with `createdAt` greater than the confirmation-request comment's
+`createdAt`.
+
+The author has responded. The reply text is **not** parsed by
+the bot — the triaging maintainer reads the reply alongside the
+proposal in
+[`interaction-loop.md`](interaction-loop.md) and decides
+whether the response is affirmative. If the maintainer reads
+the reply as a non-affirmative response ("still working on X",
+a follow-up question, etc.) they override the proposal to
+`skip` or `[O]ping`. The bot's only job is to surface the PR
+with the reply visible.
+
 ### `copilot_review_stale`
 
 The PR has at least one unresolved review thread whose first
diff --git a/.claude/skills/pr-management-triage/comment-templates.md 
b/.claude/skills/pr-management-triage/comment-templates.md
index b5adaa2..5cbc236 100644
--- a/.claude/skills/pr-management-triage/comment-templates.md
+++ b/.claude/skills/pr-management-triage/comment-templates.md
@@ -63,7 +63,7 @@ Rules for the footer:
 
 - **Always include it** on every contributor-facing comment the
   skill posts — `draft`, `comment-only`, `close`,
-  `review-nudge`, `reviewer-ping`, `mark-ready-with-ping`,
+  `review-nudge`, `reviewer-ping`, `request-author-confirmation`,
   `stale-draft-close`, `inactive-to-draft`,
   `stale-workflow-approval`. The only exception is the
   `suspicious-changes` template, which is short, operationally
@@ -277,50 +277,67 @@ in-thread reply.
 
 ---
 
-## Mark ready with ping
+## Request author confirmation
 
-*(`mark-ready-with-ping` — promote-and-invite-reviewers comment)*
+*(`request-author-confirmation` — ask-author-if-ready comment)*
 
-Used when the action is `mark-ready-with-ping` (see
-[`actions.md#mark-ready-with-ping`](actions.md)). The PR's
-only outstanding signal is unresolved review threads, the
+Used when the action is `request-author-confirmation` (see
+[`actions.md#request-author-confirmation`](actions.md)). The
+PR's only outstanding signal is unresolved review threads, the
 
[`unresolved_threads_only_likely_addressed`](classify-and-act.md#unresolved_threads_only_likely_addressed)
-heuristic fired, and we are promoting the PR to
-`ready for maintainer review` while inviting the original
-reviewer(s) to confirm the resolution.
+heuristic fired (engagement signal — not resolution signal),
+and we are asking the author to confirm before the PR is
+promoted into the maintainer review queue.
+
+The body **must** include the literal marker string
+`ready for maintainer review confirmation` verbatim. The
+[`viewer_confirmation_request_present`](classify-and-act.md#viewer_confirmation_request_present)
+precondition searches for that exact text on subsequent sweeps;
+paraphrasing it breaks the gated flow.
 
 ```markdown
-@<author> — Your unresolved review thread(s) from <reviewers> appear to have 
been addressed (post-review commits and/or in-thread replies on every thread, 
with the latest commit pushed after the most recent thread). I've added the 
`ready for maintainer review` label so the PR re-enters the maintainer review 
queue.
+@<author> — There are <N> unresolved review thread(s) on this PR from 
<reviewers>, and you have engaged with each one (post-review commits and/or 
in-thread replies). Could you confirm whether you believe the feedback is fully 
addressed and the PR is ready for maintainer review confirmation?
+
+If yes, reply here (a short "yes / ready" is fine) and an <PROJECT> maintainer 
will pick the PR up from the review queue on the next sweep.
 
-<reviewers> — could you take another look when you have a chance? If you agree 
the feedback was addressed, please mark the threads as resolved so the queue 
signal stays accurate. If a thread still needs work, please reply in-line — 
@<author> will follow up.
+If you are still working on a thread, please reply with what is outstanding so 
the threads stay unresolved on purpose.
 
 <ai_attribution_footer>
 ```
 
 Notes on the body:
 
-- **`@<author>` is mentioned once at the top.** They get one
-  notification with the rationale (so they understand why the
-  label appeared) and a clear ask if a thread comes back open.
-- **Every reviewer with an unresolved thread is `@`-mentioned
-  once** in the second paragraph. They get the prompt that
-  matters for them — "please re-look and resolve the threads if
-  you agree".
-- **No "no rush" line.** Unlike the `draft` / `comment-only`
-  templates, this one is announcing forward motion (PR
-  promoted), not asking the author to fix something — the
-  decompression line would read as out of place.
-- **No "thanks!"** — per the global tone rules, sign-offs are
-  noise.
-- **The `<ai_attribution_footer>` still applies** so the
-  reviewer knows the promotion is AI-drafted; if the
-  heuristic was wrong they have a clear cue to push back
-  rather than assuming a maintainer made the call.
-
-If the heuristic was wrong (the reviewer disagrees that the
-threads are addressed), the reviewer can re-open a thread,
-remove the label, or comment back — the PR re-enters the
-unresolved-threads triage path on the next sweep.
+- **`@<author>` is mentioned once at the top.** They are the
+  only person whose input we need in this step.
+- **No `<reviewers>` `@`-mention.** Reviewers are reached
+  through the `ready for maintainer review` queue once the
+  author confirms — pinging them here would push a notification
+  built on the engagement signal alone, which is the failure
+  mode this two-sweep flow exists to avoid.
+- **The marker string `ready for maintainer review
+  confirmation`** appears verbatim in the first paragraph.
+  Do not edit the wording around it in a way that breaks the
+  substring match (case-sensitive).
+- **No "no rush" line.** The author is the only one who can
+  move the PR forward at this step; framing the ask softly
+  matters more than a decompression line.
+- **The `<ai_attribution_footer>` applies** — this is a
+  contributor-facing comment drafted by the bot, and the
+  author should know that.
+
+If the author replies affirmatively, the next sweep classifies
+the PR as
+[`author_confirmation_received`](classify-and-act.md#author_confirmation_received)
+and the triaging maintainer is offered the
+[`mark-ready`](actions.md#mark-ready--add-ready-for-maintainer-review-label)
+action with the author's reply visible alongside the proposal.
+If the author replies with "still working on X" or a clarifying
+question, the maintainer overrides the proposal to `skip` or
+`[O]ping` from the group menu.
+
+If the author is silent past the cooldown, the
+[stale author-confirm-request 
sweep](stale-sweeps.md#sweep-5--stale-author-confirm-request)
+takes over.
 
 ---
 
diff --git a/.claude/skills/pr-management-triage/interaction-loop.md 
b/.claude/skills/pr-management-triage/interaction-loop.md
index 63704a3..39110f4 100644
--- a/.claude/skills/pr-management-triage/interaction-loop.md
+++ b/.claude/skills/pr-management-triage/interaction-loop.md
@@ -47,17 +47,33 @@ the groups in this fixed order:
 8. `(deterministic_flag, ping)` — batchable (unresolved threads
    from collaborators).
 9. `(stale_review, ping)` — batchable.
-10. `(deterministic_flag, mark-ready-with-ping)` — batchable
-    (unresolved threads that the heuristic believes are
-    addressed; presented just before the plain mark-ready group
-    because both end with the `ready for maintainer review`
-    label going on).
-11. `(passing, mark-ready)` — batchable.
-12. `(stale_draft, close)` — batchable but with extra per-PR
+10. `(deterministic_flag, request-author-confirmation)` —
+    batchable (unresolved threads where the engagement
+    heuristic fired; we ask the author whether the PR is
+    ready for maintainer review before any label or reviewer
+    ping is generated — the first leg of the two-sweep gate).
+11. `(author_confirmed_ready, mark-ready)` — batchable
+    (presented just before the plain mark-ready group because
+    both end with the `ready for maintainer review` label
+    going on). The author's reply is shown in the per-PR row
+    so the maintainer can read it before confirming `[A]ll` —
+    a non-affirmative reply is the maintainer's cue to
+    `[P]ick` the PR out and override to `skip` or `ping`.
+12. `(passing, mark-ready)` — batchable.
+13. `(stale_draft, close)` — batchable but with extra per-PR
     confirm inside the batch (these are rarely wrong but when
     wrong they're very wrong).
-13. `(inactive_open, draft)` — batchable.
-14. `(stale_workflow_approval, draft)` — batchable.
+14. `(inactive_open, draft)` — batchable.
+15. `(stale_workflow_approval, draft)` — batchable.
+
+Skipped (filtered before group presentation) but worth noting
+for completeness: `awaiting_author_confirmation` PRs (we asked
+the author, they have not yet replied, and we are still inside
+the cooldown) classify as `skip` in
+[row 14b](classify-and-act.md#decision-table) and never form
+a group. They reappear once the author replies (→ group 11) or
+when the cooldown lapses (→ Sweep 5 in
+[`stale-sweeps.md`](stale-sweeps.md)).
 
 The ordering is chosen so the maintainer always faces the
 riskiest decisions first, while their attention is fresh. The
@@ -211,7 +227,7 @@ safe alternatives:
 | `rebase` | `comment`, `skip` |
 | `rerun` | `comment`, `skip` |
 | `mark-ready` | `skip` |
-| `mark-ready-with-ping` | `ping` (fall back to plain reviewer ping if the 
maintainer thinks the heuristic over-reached), `skip` |
+| `request-author-confirmation` | `ping` (skip the author-confirmation step 
and post the plain reviewer-ping body directly if the maintainer thinks the 
engagement heuristic over-reached), `skip` |
 | `ping` | `comment`, `skip` |
 | `close` (deterministic_flag) | — (no overrides — use `[E]` to downgrade 
individually) |
 | `close` (stale_draft) | `draft`, `skip` |
@@ -341,7 +357,7 @@ PRs acted on:    22
   - rebased:           4
   - reruns triggered:  3
   - marked ready:      3
-  - marked ready w/ ping:  1
+  - author-confirm requests:  1
   - pings posted:      2
 PRs skipped:     15   (12 already triaged / inside grace, 2 bot, 1 
collaborator)
 PRs left pending: 10   (reached [Q] before classifying)
diff --git a/.claude/skills/pr-management-triage/rationale.md 
b/.claude/skills/pr-management-triage/rationale.md
index ba1ce21..ff1962d 100644
--- a/.claude/skills/pr-management-triage/rationale.md
+++ b/.claude/skills/pr-management-triage/rationale.md
@@ -324,29 +324,151 @@ The shape of the failures determines the action:
 - Otherwise (≤ 2 failures, no conflict, branch up-to-date) →
   `rerun`. Most "two-failure" cases on a clean PR are flakes.
 
-### Rows 14, 15 — `mark-ready-with-ping` vs `ping`
-
-Both fire when the only signal is unresolved review threads.
-Difference is what we believe about the threads:
-
-- `ping` is the safe default — threads are unresolved, may not
-  yet be addressed, nudge the author to fix or explain.
-- `mark-ready-with-ping` is the optimistic path — threads are
-  unresolved but the author has already engaged (post-review
-  commit, or in-thread reply, *and* the latest commit post-dates
-  the most recent unresolved thread). The PR is plausibly ready
-  for the maintainer to take another look; we promote it with
-  the `ready for maintainer review` label *and* ping the
-  reviewer to confirm and resolve their threads.
-
-The `unresolved_threads_only_likely_addressed` heuristic is conservative on
-purpose. False-negative degrades to plain `ping` (cheap). False-
-positive would advance a PR that isn't actually ready, which is
-the worse failure mode. The maintainer still confirms; the
-posted comment explicitly invites the reviewer to push back if a
-thread is not actually addressed, so a heuristic false-positive
-self-corrects on the next round-trip rather than silently landing
-the PR.
+### Rows 14a, 14b, 14c, 15 — the two-sweep author-confirmation gate
+
+All four rows handle PRs whose only outstanding signal is
+unresolved review threads. The split is about *what stage of
+the gate* the PR is in:
+
+- **Row 14a — `author_confirmed_ready` → `mark-ready`.** We
+  asked the author on a prior sweep; the author replied.
+  Silently apply the `ready for maintainer review` label. No
+  comment, no reviewer `@`-mention; the label is the queue
+  signal. Reviewers reach the PR through the queue, not via
+  the bot.
+- **Row 14b — `awaiting_author_confirmation` → `skip`.** We
+  asked the author on a prior sweep; the author has not
+  replied yet and the cooldown has not elapsed. Do nothing
+  this sweep. The same row stays matched on subsequent sweeps
+  until either the author replies (row 14a takes over) or
+  Sweep 5 in [`stale-sweeps.md`](stale-sweeps.md) reroutes
+  the PR to plain `ping`.
+- **Row 14c — engagement signal present, no prior request →
+  `request-author-confirmation`.** The engagement heuristic
+  (`unresolved_threads_only_likely_addressed`) fires and we
+  have not asked the author yet. Post an author-only comment
+  asking whether the PR is ready. No label, no reviewer
+  mention.
+- **Row 15 — engagement signal absent → `ping`.** The threads
+  are unresolved and the author has not engaged with them in
+  a way the heuristic recognises. The safe default — nudge
+  the author (or, in the inspection-confirmed variant, the
+  reviewer) without making any claim about resolution.
+
+#### Why a two-sweep gate at all
+
+The earlier single-sweep `mark-ready-with-ping` action
+collapsed the entire flow into one step: heuristic match →
+maintainer confirm → label added + reviewer `@`-mentioned.
+The structural problem was that the engagement heuristic is
+an *engagement* signal, not a *resolution* signal:
+
+- A post-review commit does not guarantee the commit
+  addresses the specific thread (it can touch unrelated
+  files, fix only one of several open threads, or be a
+  follow-up to a different review).
+- An in-thread author reply does not guarantee the reply
+  resolves the thread (it can be a clarifying question, a
+  partial fix, or pushback on the reviewer's framing).
+
+The triaging maintainer's confirmation on the single-sweep
+action was an endorsement of "the heuristic looks plausible",
+not "the threads are definitively resolved". But the outgoing
+comment named the original reviewer(s) and asserted the
+threads "appear to have been addressed" — a stronger claim
+than the underlying evidence supported. False positives
+landed on the original reviewers as push notifications and
+asked them to do the verification work the heuristic could
+not.
+
+The two-sweep gate moves the verification step to the only
+party who reliably knows whether the feedback is addressed:
+the author. Trade-off is one sweep of latency in exchange for
+removing the reviewer-mention path entirely and shifting
+false-positive cost from "another maintainer's notification
+queue" to "one extra round-trip in the author/bot
+conversation".
+
+#### Why the label is silent on row 14a
+
+When row 14a fires, the label is applied with no comment.
+This is the same recipe as plain `mark-ready` (row 20). The
+reasoning:
+
+- The author already knows they have been promoted — they
+  just replied affirmatively to the bot's question on the
+  previous sweep, and the label appearing is the visible
+  confirmation that the answer was accepted.
+- Reviewers reach the PR through the `ready for maintainer
+  review` queue, which is a pull signal rather than a push
+  notification. Adding a `@`-mention here would be the
+  exact noise pattern row 14c was designed to remove,
+  just one sweep later.
+
+If reviewer attention is genuinely needed beyond the queue
+signal (e.g. a thread that the maintainer reading the
+proposal believes the author still needs to address), the
+maintainer reads the author's reply and either `[P]`-picks
+the PR out for an override to plain `ping`, or skips. The
+in-the-loop maintainer is more informed than the bot's
+heuristic and can call it correctly.
+
+#### Why row 14c posts a comment but no label
+
+The asymmetry with row 14a is deliberate. At row 14c we have
+*engagement* but not *resolution* — promoting the PR to the
+maintainer queue at this stage would re-introduce the
+single-sweep failure mode (label on a PR that may not
+actually be ready, surfaced to other maintainers who then
+discover the gap). Posting the question without the label
+keeps the PR in the author's lane until the author signals
+otherwise.
+
+The cost is one sweep of latency in the happy path. The
+benefit is that the label, when it is eventually added, is
+gated on the author's own statement that the PR is ready —
+which is the strongest cheap signal available without
+forcing the bot to read the diff or parse the reviewer's
+comments.
+
+#### Why row 14b is `skip`, not a fresh comment
+
+Once we have asked the author and we are still inside the
+cooldown, posting a second comment would be the bot
+nagging. The author has the question; they know what is
+expected; the silence is informative. Sweep 5 in
+[`stale-sweeps.md`](stale-sweeps.md) handles the escalation
+deterministically once 7 days have elapsed, so there is no
+need for the active-triage path to act in the interim.
+
+#### What happens to the `<author-reply>` body
+
+Row 14a's precondition is *any* author comment after our
+request, not "an affirmative author comment". The bot does
+not parse the reply text — natural-language affirmation
+detection is brittle and would re-introduce a heuristic
+failure mode in the second leg of the flow. Instead, the
+triaging maintainer reads the author's reply alongside the
+proposal in the
+[group screen](interaction-loop.md#group-ordering). If the
+reply is affirmative the maintainer accepts the proposal in
+one keystroke. If the reply is "actually I'm still working
+on X" the maintainer overrides to `skip` (or `[O]`-overrides
+to plain `ping` to re-surface the unresolved-thread
+conversation). The bot's job is to put the PR and the reply
+in front of a person who can read.
+
+#### `unresolved_threads_only_likely_addressed` stays conservative
+
+The heuristic still fires only when the latest commit
+post-dates the most recent unresolved thread AND every
+unresolved thread has either an in-thread author reply or a
+post-thread commit. The change is in what we *do* on
+matches, not in the matching condition. Tightening the
+heuristic further (e.g. requiring per-thread commit
+attribution) would gain little once the author-confirmation
+gate is in place: the gate already filters the
+false-positives that would otherwise reach the reviewer.
 
 ### Row 16 — no real CI ran, mergeable
 
diff --git a/.claude/skills/pr-management-triage/stale-sweeps.md 
b/.claude/skills/pr-management-triage/stale-sweeps.md
index c41c0f0..666de62 100644
--- a/.claude/skills/pr-management-triage/stale-sweeps.md
+++ b/.claude/skills/pr-management-triage/stale-sweeps.md
@@ -5,7 +5,7 @@
 
 The stale-sweep phase runs after the interactive triage is
 done (Step 5 in [`SKILL.md`](SKILL.md)). Its job is to clear
-three categories of PRs that have gone silent:
+four categories of PRs that have gone silent:
 
 1. **Stale drafts** — drafts that haven't moved in weeks; either
    triaged and ghosted, or never triaged and drifted.
@@ -14,6 +14,11 @@ three categories of PRs that have gone silent:
 3. **Stale workflow-approval PRs** — first-time-contributor
    PRs awaiting workflow approval that have sat for over 4
    weeks without the author pushing new commits.
+4. **Stale author-confirm-requests** — PRs where the bot asked
+   the author to confirm readiness for maintainer review (the
+   first leg of the [row 14c](classify-and-act.md#decision-table)
+   two-sweep flow) and the author has been silent past the
+   cooldown.
 
 Each category has deterministic trigger criteria, a fixed
 action, and a canned comment. They are surfaced through the
@@ -245,6 +250,80 @@ since maintainer comment, no author reply, branch has
 
 ---
 
+## Sweep 5 — Stale author-confirm-request
+
+When a PR has a pending author-confirmation request from a
+prior sweep (the first leg of the
+[row 14c](classify-and-act.md#decision-table) two-sweep flow)
+and the author has not replied within the cooldown, this sweep
+proposes a fallback action so the PR does not sit indefinitely
+in the "asked, awaiting reply" limbo state.
+
+### Trigger
+
+- 
[`viewer_confirmation_request_present`](classify-and-act.md#viewer_confirmation_request_present)
+  is true (we posted the request, the head SHA has not advanced
+  since).
+- 
[`pending_author_confirmation`](classify-and-act.md#pending_author_confirmation)
+  is true (no author reply after our request).
+- `<now> - confirmation_request_at >= 7 days`, where
+  `confirmation_request_at` is the `createdAt` of the viewer's
+  most recent comment carrying the
+  `ready for maintainer review confirmation` marker.
+
+The same 7-day window used by
+[Sweep 4](#sweep-4--stale-ready-for-review-label) applies here
+— the symmetry is intentional: in both cases the author has
+gone silent after we asked them for input on a PR they own.
+
+### Action
+
+`ping` with the
+[`reviewer-ping` author-primary body](comment-templates.md#reviewer-ping)
+(unresolved threads from collaborators). The new ping makes
+the unresolved-thread state itself the topic again — the
+confirmation request was a softer ask that did not work, so
+the next sweep escalates to the normal unresolved-thread nudge.
+
+Do **not** strip the prior confirmation-request comment — it
+remains as part of the PR history, and a contributor returning
+later can see both pings in order.
+
+**Reason string.** *"Author confirmation requested N days ago,
+no reply — escalating to plain reviewer ping"*.
+
+### Group behaviour
+
+Batchable with simple `[A]ll` — the action is a single
+non-destructive comment, recoverable by the maintainer if it
+fires on the wrong PR.
+
+### Why not `close` or `draft`?
+
+`close` would punish a contributor whose only "fault" is
+missing a confirmation question; `draft` would lose the PR's
+review-ready posture even though every other signal
+(CI green, no conflicts) is healthy. Plain `ping` is the
+minimum escalation that re-surfaces the PR to the original
+reviewer pool without prejudging where the responsibility
+lies.
+
+### Override
+
+If the maintainer reading the proposal sees the unresolved
+threads are obviously addressed (e.g. the author engaged
+substantively in-thread but never replied to our
+confirmation), they can `[O]`-override the group to
+`mark-ready` — that path skips the ping entirely and just
+applies the label, treating the author's earlier in-thread
+engagement as the implicit confirmation. The override is
+deliberately not the default because a programmatic test for
+"engagement was substantive" would re-introduce exactly the
+false-positive risk the two-sweep gate was designed to
+eliminate.
+
+---
+
 ## Order of sweeps
 
 1. Sweep 1a (triaged drafts, 7d)
@@ -253,6 +332,7 @@ since maintainer comment, no author reply, branch has
 4. Sweep 3 (stale WF approval, 4w)
 5. Sweep 4a (stale ready-label, healthy, 7d) → strip
 6. Sweep 4b (stale ready-label, rotted, 7d) → close
+7. Sweep 5 (stale author-confirm-request, 7d) → ping
 
 Run 1a before 1b so a draft that's both "triaged 7d ago" and
 "never-triaged 2w ago" (the triage comment is recent but the
@@ -264,6 +344,13 @@ the default search excluded), so there is no overlap with 
the
 earlier sweeps. 4a runs before 4b so the cheap label-tidying
 batch lands before the per-PR-confirm `close` group.
 
+Sweep 5 runs last because its candidate set is also disjoint
+from the earlier sweeps — PRs holding a confirmation-request
+comment do not carry the `ready for maintainer review` label
+yet (the label is the second-leg outcome), and their author
+silence is more recent than the 4-week thresholds in Sweeps 2
+and 3.
+
 ---
 
 ## What the sweeps do NOT do
diff --git a/projects/_template/pr-management-triage-comment-templates.md 
b/projects/_template/pr-management-triage-comment-templates.md
index 798e5e4..7ec8cbc 100644
--- a/projects/_template/pr-management-triage-comment-templates.md
+++ b/projects/_template/pr-management-triage-comment-templates.md
@@ -14,7 +14,7 @@
     - [`review-nudge` (reviewer-re-review)](#review-nudge-reviewer-re-review)
     - [`reviewer-ping` (author-primary)](#reviewer-ping-author-primary)
     - [`reviewer-ping` (reviewer-re-review)](#reviewer-ping-reviewer-re-review)
-    - [`mark-ready-with-ping`](#mark-ready-with-ping)
+    - [`request-author-confirmation`](#request-author-confirmation)
     - [`stale-draft-close` (triaged)](#stale-draft-close-triaged)
     - [`stale-draft-close` (untriaged)](#stale-draft-close-untriaged)
     - [`inactive-to-draft`](#inactive-to-draft)
@@ -160,12 +160,21 @@ This is **not** a rejection — you're welcome to open a 
new PR addressing the i
 <ai_attribution_footer>
 ```
 
-### `mark-ready-with-ping`
+### `request-author-confirmation`
+
+The body **must** include the literal marker string
+`ready for maintainer review confirmation` verbatim — the
+framework's
+[`viewer_confirmation_request_present`](../../.claude/skills/pr-management-triage/classify-and-act.md#viewer_confirmation_request_present)
+precondition searches for that exact text. Do not paraphrase
+that string when adapting the rest of the body.
 
 ```markdown
-@<author> — Your unresolved review thread(s) from <reviewers> appear to have 
been addressed (post-review commits and/or in-thread replies on every thread, 
with the latest commit pushed after the most recent thread). I've added the 
`ready for maintainer review` label so the PR re-enters the maintainer review 
queue.
+@<author> — There are <N> unresolved review thread(s) on this PR, and you have 
engaged with each one (post-review commits and/or in-thread replies). Could you 
confirm whether you believe the feedback is fully addressed and the PR is ready 
for maintainer review confirmation?
+
+If yes, reply here (a short "yes / ready" is fine) and an Apache Airflow 
maintainer will pick the PR up from the review queue on the next sweep.
 
-<reviewers> — could you take another look when you have a chance? If you agree 
the feedback was addressed, please mark the threads as resolved so the queue 
signal stays accurate. If a thread still needs work, please reply in-line — 
@<author> will follow up.
+If you are still working on a thread, please reply with what is outstanding so 
the threads stay unresolved on purpose.
 
 <ai_attribution_footer>
 ```

Reply via email to