[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648) - #65848

Merged
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test
Apr 26, 2026
Merged

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648)#65848
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Add pr-triage skill for maintainer-driven PR queue sweep

A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.

Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.

Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.

Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst

  • pr-triage: add Copilot-review staleness + prefer author-pings

Two rule refinements surfaced while running the skill on
apache/airflow:

  1. New classification stale_copilot_review. When a PR has an
    unresolved review thread authored by a Copilot-review bot
    (copilot-pull-request-reviewer[bot] and siblings) and the
    comment is >= 14 days old with no author reply, the skill
    classifies it as stale_copilot_review and suggests draft
    with a new "Unaddressed Copilot review" violation. The
    14-day window is deliberately longer than the 24h/96h CI
    grace — review feedback takes longer to address and a
    two-day nudge would be noisy.

  2. Strongly prefer pinging the PR author over the reviewer on
    the ping action. Both comment families (review-nudge for
    stale CHANGES_REQUESTED, reviewer-ping for unresolved
    threads) now document an author-primary default body and a
    reviewer-re-review variant. The reviewer-re-review body is
    only used after an explicit inspection of the post-review
    diff + in-thread replies confirms the feedback has been
    addressed in code or explained away. The previous logic
    (which switched on whether the author had @-mentioned the
    reviewer) put the re-review request on the reviewer's desk
    even when the actual work was still on the author's side.

Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.

  • pr-triage: never suggest rebase on CONFLICTING PRs — route to draft

Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.

  • suggested-actions.md: the "mergeable == CONFLICTING" rule now
    maps to draft regardless of other signals. An explicit hard
    rule spells out why.
  • actions.md#rebase: a mergeable check runs before the
    update-branch call; if the state is CONFLICTING the action
    refuses with a route-to-draft hint. If a non-CONFLICTING call
    still 422s, the skill does not retry — it falls through to
    draft.
  • SKILL.md Step 3 table updated to reflect the new mapping.
  • pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks

Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.

Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.

  • pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body

Two related changes for the stale_copilot_review classification:

  • Tighten the trigger threshold. Copilot reviews that sit unaddressed
    for a week already signal a stalled PR — waiting two weeks before
    drafting adds queue pressure without useful signal.

  • Revise the draft-comment language to explicitly call out that some
    Copilot suggestions may be incorrect or irrelevant, and that it is
    still the author's responsibility to respond — apply the fix, reply
    in-thread explaining why it does not apply, or resolve the thread
    if the feedback is no longer relevant. Previously the wording could
    be read as 'please do everything Copilot said', which is the wrong
    bar.

  • pr-triage: make action_required REST check primary for pending_workflow_approval

A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.

Changes:

  • classify.md: rewrite C1 (pending_workflow_approval) so the
    repo-level REST call GET /repos/.../actions/runs?status=action_required
    is the primary signal, not a fallback. Index the response by
    head_sha once per page. Call out that the rollup-based check
    alone is not sufficient and explain why.

  • classify.md: rewrite 'Verifying real CI ran' from an optional
    note into a mandatory pre-passing guard. Expand the real-CI
    pattern list to include Tests (exact), CodeQL, and
    'Check newsfragment PR number'.

  • fetch-and-batch.md: add an 'Mandatory: action_required run
    index per page' section that documents the REST call as part of
    the per-page fetch plan (one extra round-trip per page, well
    inside the budget).

  • pr-triage: spell out author responsibility to mark threads resolved

The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.

Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.

  • pr-triage: mandatory pre-check against action_required on mark-ready

Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.

Changes:

  • actions.md §mark-ready: add a MUST-DO pre-mutation check —
    GET /repos///actions/runs?head_sha=&status=
    action_required returning any result is a hard refuse. On
    refuse, reclassify the PR as pending_workflow_approval and
    route accordingly instead of silently dropping the mutation.

  • SKILL.md Golden rules: add rule 1b elevating the check to the
    top-of-file contract so a skill implementor can't miss it.
    The rationale (fast bot checks finish first while Tests /
    CodeQL / newsfragment sit in action_required) is spelled out
    so nobody thinks this is belt-and-braces redundancy.

  • pr-triage: add AI-attribution footer to contributor comments

Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.

The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.

SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)

Co-authored-by: Jarek Potiuk jarek@potiuk.com

…age (#65648)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@potiuk
potiukforce-pushed the backport-0ed3e73-v3-2-test branch from ff81d78 to 22df0d1CompareApril 26, 2026 16:59
@potiuk
potiuk merged commit d7d5b9d into v3-2-testApr 26, 2026
111 checks passed
@potiuk
potiuk deleted the backport-0ed3e73-v3-2-test branch April 26, 2026 19:45
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@vatsrahul1001vatsrahul1001 added the changelog:skip Changes that should be skipped from the changelog (CI, tests, etc..) label May 18, 2026
@vatsrahul1001vatsrahul1001 added this to the Airflow 3.2.2 milestone May 18, 2026
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-toolschangelog:skipChanges that should be skipped from the changelog (CI, tests, etc..)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@potiuk@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648) - #65848

Merged
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test
Apr 26, 2026
Merged

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648)#65848
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Add pr-triage skill for maintainer-driven PR queue sweep

A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.

Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.

Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.

Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst

  • pr-triage: add Copilot-review staleness + prefer author-pings

Two rule refinements surfaced while running the skill on
apache/airflow:

  1. New classification stale_copilot_review. When a PR has an
    unresolved review thread authored by a Copilot-review bot
    (copilot-pull-request-reviewer[bot] and siblings) and the
    comment is >= 14 days old with no author reply, the skill
    classifies it as stale_copilot_review and suggests draft
    with a new "Unaddressed Copilot review" violation. The
    14-day window is deliberately longer than the 24h/96h CI
    grace — review feedback takes longer to address and a
    two-day nudge would be noisy.

  2. Strongly prefer pinging the PR author over the reviewer on
    the ping action. Both comment families (review-nudge for
    stale CHANGES_REQUESTED, reviewer-ping for unresolved
    threads) now document an author-primary default body and a
    reviewer-re-review variant. The reviewer-re-review body is
    only used after an explicit inspection of the post-review
    diff + in-thread replies confirms the feedback has been
    addressed in code or explained away. The previous logic
    (which switched on whether the author had @-mentioned the
    reviewer) put the re-review request on the reviewer's desk
    even when the actual work was still on the author's side.

Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.

  • pr-triage: never suggest rebase on CONFLICTING PRs — route to draft

Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.

  • suggested-actions.md: the "mergeable == CONFLICTING" rule now
    maps to draft regardless of other signals. An explicit hard
    rule spells out why.
  • actions.md#rebase: a mergeable check runs before the
    update-branch call; if the state is CONFLICTING the action
    refuses with a route-to-draft hint. If a non-CONFLICTING call
    still 422s, the skill does not retry — it falls through to
    draft.
  • SKILL.md Step 3 table updated to reflect the new mapping.
  • pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks

Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.

Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.

  • pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body

Two related changes for the stale_copilot_review classification:

  • Tighten the trigger threshold. Copilot reviews that sit unaddressed
    for a week already signal a stalled PR — waiting two weeks before
    drafting adds queue pressure without useful signal.

  • Revise the draft-comment language to explicitly call out that some
    Copilot suggestions may be incorrect or irrelevant, and that it is
    still the author's responsibility to respond — apply the fix, reply
    in-thread explaining why it does not apply, or resolve the thread
    if the feedback is no longer relevant. Previously the wording could
    be read as 'please do everything Copilot said', which is the wrong
    bar.

  • pr-triage: make action_required REST check primary for pending_workflow_approval

A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.

Changes:

  • classify.md: rewrite C1 (pending_workflow_approval) so the
    repo-level REST call GET /repos/.../actions/runs?status=action_required
    is the primary signal, not a fallback. Index the response by
    head_sha once per page. Call out that the rollup-based check
    alone is not sufficient and explain why.

  • classify.md: rewrite 'Verifying real CI ran' from an optional
    note into a mandatory pre-passing guard. Expand the real-CI
    pattern list to include Tests (exact), CodeQL, and
    'Check newsfragment PR number'.

  • fetch-and-batch.md: add an 'Mandatory: action_required run
    index per page' section that documents the REST call as part of
    the per-page fetch plan (one extra round-trip per page, well
    inside the budget).

  • pr-triage: spell out author responsibility to mark threads resolved

The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.

Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.

  • pr-triage: mandatory pre-check against action_required on mark-ready

Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.

Changes:

  • actions.md §mark-ready: add a MUST-DO pre-mutation check —
    GET /repos///actions/runs?head_sha=&status=
    action_required returning any result is a hard refuse. On
    refuse, reclassify the PR as pending_workflow_approval and
    route accordingly instead of silently dropping the mutation.

  • SKILL.md Golden rules: add rule 1b elevating the check to the
    top-of-file contract so a skill implementor can't miss it.
    The rationale (fast bot checks finish first while Tests /
    CodeQL / newsfragment sit in action_required) is spelled out
    so nobody thinks this is belt-and-braces redundancy.

  • pr-triage: add AI-attribution footer to contributor comments

Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.

The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.

SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)

Co-authored-by: Jarek Potiuk jarek@potiuk.com

…age (#65648)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@potiuk
potiukforce-pushed the backport-0ed3e73-v3-2-test branch from ff81d78 to 22df0d1CompareApril 26, 2026 16:59
@potiuk
potiuk merged commit d7d5b9d into v3-2-testApr 26, 2026
111 checks passed
@potiuk
potiuk deleted the backport-0ed3e73-v3-2-test branch April 26, 2026 19:45
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@vatsrahul1001vatsrahul1001 added the changelog:skip Changes that should be skipped from the changelog (CI, tests, etc..) label May 18, 2026
@vatsrahul1001vatsrahul1001 added this to the Airflow 3.2.2 milestone May 18, 2026
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-toolschangelog:skipChanges that should be skipped from the changelog (CI, tests, etc..)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@potiuk@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648) - #65848

Merged
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test
Apr 26, 2026
Merged

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648)#65848
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Add pr-triage skill for maintainer-driven PR queue sweep

A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.

Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.

Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.

Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst

  • pr-triage: add Copilot-review staleness + prefer author-pings

Two rule refinements surfaced while running the skill on
apache/airflow:

  1. New classification stale_copilot_review. When a PR has an
    unresolved review thread authored by a Copilot-review bot
    (copilot-pull-request-reviewer[bot] and siblings) and the
    comment is >= 14 days old with no author reply, the skill
    classifies it as stale_copilot_review and suggests draft
    with a new "Unaddressed Copilot review" violation. The
    14-day window is deliberately longer than the 24h/96h CI
    grace — review feedback takes longer to address and a
    two-day nudge would be noisy.

  2. Strongly prefer pinging the PR author over the reviewer on
    the ping action. Both comment families (review-nudge for
    stale CHANGES_REQUESTED, reviewer-ping for unresolved
    threads) now document an author-primary default body and a
    reviewer-re-review variant. The reviewer-re-review body is
    only used after an explicit inspection of the post-review
    diff + in-thread replies confirms the feedback has been
    addressed in code or explained away. The previous logic
    (which switched on whether the author had @-mentioned the
    reviewer) put the re-review request on the reviewer's desk
    even when the actual work was still on the author's side.

Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.

  • pr-triage: never suggest rebase on CONFLICTING PRs — route to draft

Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.

  • suggested-actions.md: the "mergeable == CONFLICTING" rule now
    maps to draft regardless of other signals. An explicit hard
    rule spells out why.
  • actions.md#rebase: a mergeable check runs before the
    update-branch call; if the state is CONFLICTING the action
    refuses with a route-to-draft hint. If a non-CONFLICTING call
    still 422s, the skill does not retry — it falls through to
    draft.
  • SKILL.md Step 3 table updated to reflect the new mapping.
  • pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks

Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.

Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.

  • pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body

Two related changes for the stale_copilot_review classification:

  • Tighten the trigger threshold. Copilot reviews that sit unaddressed
    for a week already signal a stalled PR — waiting two weeks before
    drafting adds queue pressure without useful signal.

  • Revise the draft-comment language to explicitly call out that some
    Copilot suggestions may be incorrect or irrelevant, and that it is
    still the author's responsibility to respond — apply the fix, reply
    in-thread explaining why it does not apply, or resolve the thread
    if the feedback is no longer relevant. Previously the wording could
    be read as 'please do everything Copilot said', which is the wrong
    bar.

  • pr-triage: make action_required REST check primary for pending_workflow_approval

A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.

Changes:

  • classify.md: rewrite C1 (pending_workflow_approval) so the
    repo-level REST call GET /repos/.../actions/runs?status=action_required
    is the primary signal, not a fallback. Index the response by
    head_sha once per page. Call out that the rollup-based check
    alone is not sufficient and explain why.

  • classify.md: rewrite 'Verifying real CI ran' from an optional
    note into a mandatory pre-passing guard. Expand the real-CI
    pattern list to include Tests (exact), CodeQL, and
    'Check newsfragment PR number'.

  • fetch-and-batch.md: add an 'Mandatory: action_required run
    index per page' section that documents the REST call as part of
    the per-page fetch plan (one extra round-trip per page, well
    inside the budget).

  • pr-triage: spell out author responsibility to mark threads resolved

The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.

Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.

  • pr-triage: mandatory pre-check against action_required on mark-ready

Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.

Changes:

  • actions.md §mark-ready: add a MUST-DO pre-mutation check —
    GET /repos///actions/runs?head_sha=&status=
    action_required returning any result is a hard refuse. On
    refuse, reclassify the PR as pending_workflow_approval and
    route accordingly instead of silently dropping the mutation.

  • SKILL.md Golden rules: add rule 1b elevating the check to the
    top-of-file contract so a skill implementor can't miss it.
    The rationale (fast bot checks finish first while Tests /
    CodeQL / newsfragment sit in action_required) is spelled out
    so nobody thinks this is belt-and-braces redundancy.

  • pr-triage: add AI-attribution footer to contributor comments

Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.

The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.

SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)

Co-authored-by: Jarek Potiuk jarek@potiuk.com

…age (#65648)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@potiuk
potiukforce-pushed the backport-0ed3e73-v3-2-test branch from ff81d78 to 22df0d1CompareApril 26, 2026 16:59
@potiuk
potiuk merged commit d7d5b9d into v3-2-testApr 26, 2026
111 checks passed
@potiuk
potiuk deleted the backport-0ed3e73-v3-2-test branch April 26, 2026 19:45
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@vatsrahul1001vatsrahul1001 added the changelog:skip Changes that should be skipped from the changelog (CI, tests, etc..) label May 18, 2026
@vatsrahul1001vatsrahul1001 added this to the Airflow 3.2.2 milestone May 18, 2026
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-toolschangelog:skipChanges that should be skipped from the changelog (CI, tests, etc..)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@potiuk@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648) - #65848

Merged
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test
Apr 26, 2026
Merged

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648)#65848
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Add pr-triage skill for maintainer-driven PR queue sweep

A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.

Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.

Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.

Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst

  • pr-triage: add Copilot-review staleness + prefer author-pings

Two rule refinements surfaced while running the skill on
apache/airflow:

  1. New classification stale_copilot_review. When a PR has an
    unresolved review thread authored by a Copilot-review bot
    (copilot-pull-request-reviewer[bot] and siblings) and the
    comment is >= 14 days old with no author reply, the skill
    classifies it as stale_copilot_review and suggests draft
    with a new "Unaddressed Copilot review" violation. The
    14-day window is deliberately longer than the 24h/96h CI
    grace — review feedback takes longer to address and a
    two-day nudge would be noisy.

  2. Strongly prefer pinging the PR author over the reviewer on
    the ping action. Both comment families (review-nudge for
    stale CHANGES_REQUESTED, reviewer-ping for unresolved
    threads) now document an author-primary default body and a
    reviewer-re-review variant. The reviewer-re-review body is
    only used after an explicit inspection of the post-review
    diff + in-thread replies confirms the feedback has been
    addressed in code or explained away. The previous logic
    (which switched on whether the author had @-mentioned the
    reviewer) put the re-review request on the reviewer's desk
    even when the actual work was still on the author's side.

Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.

  • pr-triage: never suggest rebase on CONFLICTING PRs — route to draft

Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.

  • suggested-actions.md: the "mergeable == CONFLICTING" rule now
    maps to draft regardless of other signals. An explicit hard
    rule spells out why.
  • actions.md#rebase: a mergeable check runs before the
    update-branch call; if the state is CONFLICTING the action
    refuses with a route-to-draft hint. If a non-CONFLICTING call
    still 422s, the skill does not retry — it falls through to
    draft.
  • SKILL.md Step 3 table updated to reflect the new mapping.
  • pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks

Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.

Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.

  • pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body

Two related changes for the stale_copilot_review classification:

  • Tighten the trigger threshold. Copilot reviews that sit unaddressed
    for a week already signal a stalled PR — waiting two weeks before
    drafting adds queue pressure without useful signal.

  • Revise the draft-comment language to explicitly call out that some
    Copilot suggestions may be incorrect or irrelevant, and that it is
    still the author's responsibility to respond — apply the fix, reply
    in-thread explaining why it does not apply, or resolve the thread
    if the feedback is no longer relevant. Previously the wording could
    be read as 'please do everything Copilot said', which is the wrong
    bar.

  • pr-triage: make action_required REST check primary for pending_workflow_approval

A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.

Changes:

  • classify.md: rewrite C1 (pending_workflow_approval) so the
    repo-level REST call GET /repos/.../actions/runs?status=action_required
    is the primary signal, not a fallback. Index the response by
    head_sha once per page. Call out that the rollup-based check
    alone is not sufficient and explain why.

  • classify.md: rewrite 'Verifying real CI ran' from an optional
    note into a mandatory pre-passing guard. Expand the real-CI
    pattern list to include Tests (exact), CodeQL, and
    'Check newsfragment PR number'.

  • fetch-and-batch.md: add an 'Mandatory: action_required run
    index per page' section that documents the REST call as part of
    the per-page fetch plan (one extra round-trip per page, well
    inside the budget).

  • pr-triage: spell out author responsibility to mark threads resolved

The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.

Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.

  • pr-triage: mandatory pre-check against action_required on mark-ready

Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.

Changes:

  • actions.md §mark-ready: add a MUST-DO pre-mutation check —
    GET /repos///actions/runs?head_sha=&status=
    action_required returning any result is a hard refuse. On
    refuse, reclassify the PR as pending_workflow_approval and
    route accordingly instead of silently dropping the mutation.

  • SKILL.md Golden rules: add rule 1b elevating the check to the
    top-of-file contract so a skill implementor can't miss it.
    The rationale (fast bot checks finish first while Tests /
    CodeQL / newsfragment sit in action_required) is spelled out
    so nobody thinks this is belt-and-braces redundancy.

  • pr-triage: add AI-attribution footer to contributor comments

Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.

The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.

SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)

Co-authored-by: Jarek Potiuk jarek@potiuk.com

…age (#65648)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@potiuk
potiukforce-pushed the backport-0ed3e73-v3-2-test branch from ff81d78 to 22df0d1CompareApril 26, 2026 16:59
@potiuk
potiuk merged commit d7d5b9d into v3-2-testApr 26, 2026
111 checks passed
@potiuk
potiuk deleted the backport-0ed3e73-v3-2-test branch April 26, 2026 19:45
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@vatsrahul1001vatsrahul1001 added the changelog:skip Changes that should be skipped from the changelog (CI, tests, etc..) label May 18, 2026
@vatsrahul1001vatsrahul1001 added this to the Airflow 3.2.2 milestone May 18, 2026
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-toolschangelog:skipChanges that should be skipped from the changelog (CI, tests, etc..)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@potiuk@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648) - #65848

Merged
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test
Apr 26, 2026
Merged

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648)#65848
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Add pr-triage skill for maintainer-driven PR queue sweep

A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.

Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.

Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.

Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst

  • pr-triage: add Copilot-review staleness + prefer author-pings

Two rule refinements surfaced while running the skill on
apache/airflow:

  1. New classification stale_copilot_review. When a PR has an
    unresolved review thread authored by a Copilot-review bot
    (copilot-pull-request-reviewer[bot] and siblings) and the
    comment is >= 14 days old with no author reply, the skill
    classifies it as stale_copilot_review and suggests draft
    with a new "Unaddressed Copilot review" violation. The
    14-day window is deliberately longer than the 24h/96h CI
    grace — review feedback takes longer to address and a
    two-day nudge would be noisy.

  2. Strongly prefer pinging the PR author over the reviewer on
    the ping action. Both comment families (review-nudge for
    stale CHANGES_REQUESTED, reviewer-ping for unresolved
    threads) now document an author-primary default body and a
    reviewer-re-review variant. The reviewer-re-review body is
    only used after an explicit inspection of the post-review
    diff + in-thread replies confirms the feedback has been
    addressed in code or explained away. The previous logic
    (which switched on whether the author had @-mentioned the
    reviewer) put the re-review request on the reviewer's desk
    even when the actual work was still on the author's side.

Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.

  • pr-triage: never suggest rebase on CONFLICTING PRs — route to draft

Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.

  • suggested-actions.md: the "mergeable == CONFLICTING" rule now
    maps to draft regardless of other signals. An explicit hard
    rule spells out why.
  • actions.md#rebase: a mergeable check runs before the
    update-branch call; if the state is CONFLICTING the action
    refuses with a route-to-draft hint. If a non-CONFLICTING call
    still 422s, the skill does not retry — it falls through to
    draft.
  • SKILL.md Step 3 table updated to reflect the new mapping.
  • pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks

Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.

Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.

  • pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body

Two related changes for the stale_copilot_review classification:

  • Tighten the trigger threshold. Copilot reviews that sit unaddressed
    for a week already signal a stalled PR — waiting two weeks before
    drafting adds queue pressure without useful signal.

  • Revise the draft-comment language to explicitly call out that some
    Copilot suggestions may be incorrect or irrelevant, and that it is
    still the author's responsibility to respond — apply the fix, reply
    in-thread explaining why it does not apply, or resolve the thread
    if the feedback is no longer relevant. Previously the wording could
    be read as 'please do everything Copilot said', which is the wrong
    bar.

  • pr-triage: make action_required REST check primary for pending_workflow_approval

A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.

Changes:

  • classify.md: rewrite C1 (pending_workflow_approval) so the
    repo-level REST call GET /repos/.../actions/runs?status=action_required
    is the primary signal, not a fallback. Index the response by
    head_sha once per page. Call out that the rollup-based check
    alone is not sufficient and explain why.

  • classify.md: rewrite 'Verifying real CI ran' from an optional
    note into a mandatory pre-passing guard. Expand the real-CI
    pattern list to include Tests (exact), CodeQL, and
    'Check newsfragment PR number'.

  • fetch-and-batch.md: add an 'Mandatory: action_required run
    index per page' section that documents the REST call as part of
    the per-page fetch plan (one extra round-trip per page, well
    inside the budget).

  • pr-triage: spell out author responsibility to mark threads resolved

The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.

Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.

  • pr-triage: mandatory pre-check against action_required on mark-ready

Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.

Changes:

  • actions.md §mark-ready: add a MUST-DO pre-mutation check —
    GET /repos///actions/runs?head_sha=&status=
    action_required returning any result is a hard refuse. On
    refuse, reclassify the PR as pending_workflow_approval and
    route accordingly instead of silently dropping the mutation.

  • SKILL.md Golden rules: add rule 1b elevating the check to the
    top-of-file contract so a skill implementor can't miss it.
    The rationale (fast bot checks finish first while Tests /
    CodeQL / newsfragment sit in action_required) is spelled out
    so nobody thinks this is belt-and-braces redundancy.

  • pr-triage: add AI-attribution footer to contributor comments

Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.

The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.

SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)

Co-authored-by: Jarek Potiuk jarek@potiuk.com

…age (#65648)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@potiuk
potiukforce-pushed the backport-0ed3e73-v3-2-test branch from ff81d78 to 22df0d1CompareApril 26, 2026 16:59
@potiuk
potiuk merged commit d7d5b9d into v3-2-testApr 26, 2026
111 checks passed
@potiuk
potiuk deleted the backport-0ed3e73-v3-2-test branch April 26, 2026 19:45
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@vatsrahul1001vatsrahul1001 added the changelog:skip Changes that should be skipped from the changelog (CI, tests, etc..) label May 18, 2026
@vatsrahul1001vatsrahul1001 added this to the Airflow 3.2.2 milestone May 18, 2026
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-toolschangelog:skipChanges that should be skipped from the changelog (CI, tests, etc..)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@potiuk@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648) - #65848

Merged
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test
Apr 26, 2026
Merged

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648)#65848
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Add pr-triage skill for maintainer-driven PR queue sweep

A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.

Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.

Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.

Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst

  • pr-triage: add Copilot-review staleness + prefer author-pings

Two rule refinements surfaced while running the skill on
apache/airflow:

  1. New classification stale_copilot_review. When a PR has an
    unresolved review thread authored by a Copilot-review bot
    (copilot-pull-request-reviewer[bot] and siblings) and the
    comment is >= 14 days old with no author reply, the skill
    classifies it as stale_copilot_review and suggests draft
    with a new "Unaddressed Copilot review" violation. The
    14-day window is deliberately longer than the 24h/96h CI
    grace — review feedback takes longer to address and a
    two-day nudge would be noisy.

  2. Strongly prefer pinging the PR author over the reviewer on
    the ping action. Both comment families (review-nudge for
    stale CHANGES_REQUESTED, reviewer-ping for unresolved
    threads) now document an author-primary default body and a
    reviewer-re-review variant. The reviewer-re-review body is
    only used after an explicit inspection of the post-review
    diff + in-thread replies confirms the feedback has been
    addressed in code or explained away. The previous logic
    (which switched on whether the author had @-mentioned the
    reviewer) put the re-review request on the reviewer's desk
    even when the actual work was still on the author's side.

Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.

  • pr-triage: never suggest rebase on CONFLICTING PRs — route to draft

Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.

  • suggested-actions.md: the "mergeable == CONFLICTING" rule now
    maps to draft regardless of other signals. An explicit hard
    rule spells out why.
  • actions.md#rebase: a mergeable check runs before the
    update-branch call; if the state is CONFLICTING the action
    refuses with a route-to-draft hint. If a non-CONFLICTING call
    still 422s, the skill does not retry — it falls through to
    draft.
  • SKILL.md Step 3 table updated to reflect the new mapping.
  • pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks

Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.

Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.

  • pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body

Two related changes for the stale_copilot_review classification:

  • Tighten the trigger threshold. Copilot reviews that sit unaddressed
    for a week already signal a stalled PR — waiting two weeks before
    drafting adds queue pressure without useful signal.

  • Revise the draft-comment language to explicitly call out that some
    Copilot suggestions may be incorrect or irrelevant, and that it is
    still the author's responsibility to respond — apply the fix, reply
    in-thread explaining why it does not apply, or resolve the thread
    if the feedback is no longer relevant. Previously the wording could
    be read as 'please do everything Copilot said', which is the wrong
    bar.

  • pr-triage: make action_required REST check primary for pending_workflow_approval

A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.

Changes:

  • classify.md: rewrite C1 (pending_workflow_approval) so the
    repo-level REST call GET /repos/.../actions/runs?status=action_required
    is the primary signal, not a fallback. Index the response by
    head_sha once per page. Call out that the rollup-based check
    alone is not sufficient and explain why.

  • classify.md: rewrite 'Verifying real CI ran' from an optional
    note into a mandatory pre-passing guard. Expand the real-CI
    pattern list to include Tests (exact), CodeQL, and
    'Check newsfragment PR number'.

  • fetch-and-batch.md: add an 'Mandatory: action_required run
    index per page' section that documents the REST call as part of
    the per-page fetch plan (one extra round-trip per page, well
    inside the budget).

  • pr-triage: spell out author responsibility to mark threads resolved

The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.

Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.

  • pr-triage: mandatory pre-check against action_required on mark-ready

Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.

Changes:

  • actions.md §mark-ready: add a MUST-DO pre-mutation check —
    GET /repos///actions/runs?head_sha=&status=
    action_required returning any result is a hard refuse. On
    refuse, reclassify the PR as pending_workflow_approval and
    route accordingly instead of silently dropping the mutation.

  • SKILL.md Golden rules: add rule 1b elevating the check to the
    top-of-file contract so a skill implementor can't miss it.
    The rationale (fast bot checks finish first while Tests /
    CodeQL / newsfragment sit in action_required) is spelled out
    so nobody thinks this is belt-and-braces redundancy.

  • pr-triage: add AI-attribution footer to contributor comments

Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.

The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.

SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)

Co-authored-by: Jarek Potiuk jarek@potiuk.com

…age (#65648)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@potiuk
potiukforce-pushed the backport-0ed3e73-v3-2-test branch from ff81d78 to 22df0d1CompareApril 26, 2026 16:59
@potiuk
potiuk merged commit d7d5b9d into v3-2-testApr 26, 2026
111 checks passed
@potiuk
potiuk deleted the backport-0ed3e73-v3-2-test branch April 26, 2026 19:45
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@vatsrahul1001vatsrahul1001 added the changelog:skip Changes that should be skipped from the changelog (CI, tests, etc..) label May 18, 2026
@vatsrahul1001vatsrahul1001 added this to the Airflow 3.2.2 milestone May 18, 2026
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-toolschangelog:skipChanges that should be skipped from the changelog (CI, tests, etc..)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@potiuk@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648) - #65848

Merged
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test
Apr 26, 2026
Merged

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648)#65848
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Add pr-triage skill for maintainer-driven PR queue sweep

A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.

Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.

Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.

Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst

  • pr-triage: add Copilot-review staleness + prefer author-pings

Two rule refinements surfaced while running the skill on
apache/airflow:

  1. New classification stale_copilot_review. When a PR has an
    unresolved review thread authored by a Copilot-review bot
    (copilot-pull-request-reviewer[bot] and siblings) and the
    comment is >= 14 days old with no author reply, the skill
    classifies it as stale_copilot_review and suggests draft
    with a new "Unaddressed Copilot review" violation. The
    14-day window is deliberately longer than the 24h/96h CI
    grace — review feedback takes longer to address and a
    two-day nudge would be noisy.

  2. Strongly prefer pinging the PR author over the reviewer on
    the ping action. Both comment families (review-nudge for
    stale CHANGES_REQUESTED, reviewer-ping for unresolved
    threads) now document an author-primary default body and a
    reviewer-re-review variant. The reviewer-re-review body is
    only used after an explicit inspection of the post-review
    diff + in-thread replies confirms the feedback has been
    addressed in code or explained away. The previous logic
    (which switched on whether the author had @-mentioned the
    reviewer) put the re-review request on the reviewer's desk
    even when the actual work was still on the author's side.

Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.

  • pr-triage: never suggest rebase on CONFLICTING PRs — route to draft

Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.

  • suggested-actions.md: the "mergeable == CONFLICTING" rule now
    maps to draft regardless of other signals. An explicit hard
    rule spells out why.
  • actions.md#rebase: a mergeable check runs before the
    update-branch call; if the state is CONFLICTING the action
    refuses with a route-to-draft hint. If a non-CONFLICTING call
    still 422s, the skill does not retry — it falls through to
    draft.
  • SKILL.md Step 3 table updated to reflect the new mapping.
  • pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks

Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.

Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.

  • pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body

Two related changes for the stale_copilot_review classification:

  • Tighten the trigger threshold. Copilot reviews that sit unaddressed
    for a week already signal a stalled PR — waiting two weeks before
    drafting adds queue pressure without useful signal.

  • Revise the draft-comment language to explicitly call out that some
    Copilot suggestions may be incorrect or irrelevant, and that it is
    still the author's responsibility to respond — apply the fix, reply
    in-thread explaining why it does not apply, or resolve the thread
    if the feedback is no longer relevant. Previously the wording could
    be read as 'please do everything Copilot said', which is the wrong
    bar.

  • pr-triage: make action_required REST check primary for pending_workflow_approval

A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.

Changes:

  • classify.md: rewrite C1 (pending_workflow_approval) so the
    repo-level REST call GET /repos/.../actions/runs?status=action_required
    is the primary signal, not a fallback. Index the response by
    head_sha once per page. Call out that the rollup-based check
    alone is not sufficient and explain why.

  • classify.md: rewrite 'Verifying real CI ran' from an optional
    note into a mandatory pre-passing guard. Expand the real-CI
    pattern list to include Tests (exact), CodeQL, and
    'Check newsfragment PR number'.

  • fetch-and-batch.md: add an 'Mandatory: action_required run
    index per page' section that documents the REST call as part of
    the per-page fetch plan (one extra round-trip per page, well
    inside the budget).

  • pr-triage: spell out author responsibility to mark threads resolved

The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.

Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.

  • pr-triage: mandatory pre-check against action_required on mark-ready

Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.

Changes:

  • actions.md §mark-ready: add a MUST-DO pre-mutation check —
    GET /repos///actions/runs?head_sha=&status=
    action_required returning any result is a hard refuse. On
    refuse, reclassify the PR as pending_workflow_approval and
    route accordingly instead of silently dropping the mutation.

  • SKILL.md Golden rules: add rule 1b elevating the check to the
    top-of-file contract so a skill implementor can't miss it.
    The rationale (fast bot checks finish first while Tests /
    CodeQL / newsfragment sit in action_required) is spelled out
    so nobody thinks this is belt-and-braces redundancy.

  • pr-triage: add AI-attribution footer to contributor comments

Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.

The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.

SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)

Co-authored-by: Jarek Potiuk jarek@potiuk.com

…age (#65648)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@potiuk
potiukforce-pushed the backport-0ed3e73-v3-2-test branch from ff81d78 to 22df0d1CompareApril 26, 2026 16:59
@potiuk
potiuk merged commit d7d5b9d into v3-2-testApr 26, 2026
111 checks passed
@potiuk
potiuk deleted the backport-0ed3e73-v3-2-test branch April 26, 2026 19:45
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@vatsrahul1001vatsrahul1001 added the changelog:skip Changes that should be skipped from the changelog (CI, tests, etc..) label May 18, 2026
@vatsrahul1001vatsrahul1001 added this to the Airflow 3.2.2 milestone May 18, 2026
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-toolschangelog:skipChanges that should be skipped from the changelog (CI, tests, etc..)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@potiuk@vatsrahul1001
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648) - #65848

Merged
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test
Apr 26, 2026
Merged

[v3-2-test] Add pr-triage skill — maintainer-driven first-pass PR triage (#65648)#65848
potiuk merged 1 commit into
v3-2-testfrom
backport-0ed3e73-v3-2-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Add pr-triage skill for maintainer-driven PR queue sweep

A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.

Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.

Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.

Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst

  • pr-triage: add Copilot-review staleness + prefer author-pings

Two rule refinements surfaced while running the skill on
apache/airflow:

  1. New classification stale_copilot_review. When a PR has an
    unresolved review thread authored by a Copilot-review bot
    (copilot-pull-request-reviewer[bot] and siblings) and the
    comment is >= 14 days old with no author reply, the skill
    classifies it as stale_copilot_review and suggests draft
    with a new "Unaddressed Copilot review" violation. The
    14-day window is deliberately longer than the 24h/96h CI
    grace — review feedback takes longer to address and a
    two-day nudge would be noisy.

  2. Strongly prefer pinging the PR author over the reviewer on
    the ping action. Both comment families (review-nudge for
    stale CHANGES_REQUESTED, reviewer-ping for unresolved
    threads) now document an author-primary default body and a
    reviewer-re-review variant. The reviewer-re-review body is
    only used after an explicit inspection of the post-review
    diff + in-thread replies confirms the feedback has been
    addressed in code or explained away. The previous logic
    (which switched on whether the author had @-mentioned the
    reviewer) put the re-review request on the reviewer's desk
    even when the actual work was still on the author's side.

Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.

  • pr-triage: never suggest rebase on CONFLICTING PRs — route to draft

Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.

  • suggested-actions.md: the "mergeable == CONFLICTING" rule now
    maps to draft regardless of other signals. An explicit hard
    rule spells out why.
  • actions.md#rebase: a mergeable check runs before the
    update-branch call; if the state is CONFLICTING the action
    refuses with a route-to-draft hint. If a non-CONFLICTING call
    still 422s, the skill does not retry — it falls through to
    draft.
  • SKILL.md Step 3 table updated to reflect the new mapping.
  • pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks

Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.

Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.

  • pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body

Two related changes for the stale_copilot_review classification:

  • Tighten the trigger threshold. Copilot reviews that sit unaddressed
    for a week already signal a stalled PR — waiting two weeks before
    drafting adds queue pressure without useful signal.

  • Revise the draft-comment language to explicitly call out that some
    Copilot suggestions may be incorrect or irrelevant, and that it is
    still the author's responsibility to respond — apply the fix, reply
    in-thread explaining why it does not apply, or resolve the thread
    if the feedback is no longer relevant. Previously the wording could
    be read as 'please do everything Copilot said', which is the wrong
    bar.

  • pr-triage: make action_required REST check primary for pending_workflow_approval

A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.

Changes:

  • classify.md: rewrite C1 (pending_workflow_approval) so the
    repo-level REST call GET /repos/.../actions/runs?status=action_required
    is the primary signal, not a fallback. Index the response by
    head_sha once per page. Call out that the rollup-based check
    alone is not sufficient and explain why.

  • classify.md: rewrite 'Verifying real CI ran' from an optional
    note into a mandatory pre-passing guard. Expand the real-CI
    pattern list to include Tests (exact), CodeQL, and
    'Check newsfragment PR number'.

  • fetch-and-batch.md: add an 'Mandatory: action_required run
    index per page' section that documents the REST call as part of
    the per-page fetch plan (one extra round-trip per page, well
    inside the budget).

  • pr-triage: spell out author responsibility to mark threads resolved

The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.

Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.

  • pr-triage: mandatory pre-check against action_required on mark-ready

Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.

Changes:

  • actions.md §mark-ready: add a MUST-DO pre-mutation check —
    GET /repos///actions/runs?head_sha=&status=
    action_required returning any result is a hard refuse. On
    refuse, reclassify the PR as pending_workflow_approval and
    route accordingly instead of silently dropping the mutation.

  • SKILL.md Golden rules: add rule 1b elevating the check to the
    top-of-file contract so a skill implementor can't miss it.
    The rationale (fast bot checks finish first while Tests /
    CodeQL / newsfragment sit in action_required) is spelled out
    so nobody thinks this is belt-and-braces redundancy.

  • pr-triage: add AI-attribution footer to contributor comments

Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.

The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.

SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)

Co-authored-by: Jarek Potiuk jarek@potiuk.com

…age (#65648)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@potiuk
potiukforce-pushed the backport-0ed3e73-v3-2-test branch from ff81d78 to 22df0d1CompareApril 26, 2026 16:59
@potiuk
potiuk merged commit d7d5b9d into v3-2-testApr 26, 2026
111 checks passed
@potiuk
potiuk deleted the backport-0ed3e73-v3-2-test branch April 26, 2026 19:45
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
@vatsrahul1001vatsrahul1001 added the changelog:skip Changes that should be skipped from the changelog (CI, tests, etc..) label May 18, 2026
@vatsrahul1001vatsrahul1001 added this to the Airflow 3.2.2 milestone May 18, 2026
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
…age (#65648) (#65848)
* Add pr-triage skill for maintainer-driven PR queue sweep
A skill-based replacement for the triage mode of breeze pr auto-triage.
Scope is triage only — no LLM code review, no approve/request-changes,
no merging, no TUI.
Shape follows the airflow-translations convention:
.github/skills/pr-triage/ holds the canonical content;
.claude/skills/pr-triage is a committed symlink so Claude Code picks
it up without per-developer setup. .gitignore is updated to let the
symlink through, and the agentic-markdown license hook excludes
SKILL.md entry point so YAML frontmatter can stay at the top.
Also refreshes dev/breeze/doc/images/output_pr_auto-triage.{svg,txt}
— upstream's committed image was stale (boring-cyborg.yml added
labels the committed image hadn't regenerated yet), and the pre-commit
hook regenerates it on every touch of the breeze config.
Generated-by: Claude Opus 4.7 (1M context) following the guidelines
in contributing-docs/05_pull_requests.rst
* pr-triage: add Copilot-review staleness + prefer author-pings
Two rule refinements surfaced while running the skill on
apache/airflow:
1. New classification stale_copilot_review. When a PR has an
unresolved review thread authored by a Copilot-review bot
(copilot-pull-request-reviewer[bot] and siblings) and the
comment is >= 14 days old with no author reply, the skill
classifies it as stale_copilot_review and suggests draft
with a new "Unaddressed Copilot review" violation. The
14-day window is deliberately longer than the 24h/96h CI
grace — review feedback takes longer to address and a
two-day nudge would be noisy.
2. Strongly prefer pinging the PR author over the reviewer on
the ping action. Both comment families (review-nudge for
stale CHANGES_REQUESTED, reviewer-ping for unresolved
threads) now document an author-primary default body and a
reviewer-re-review variant. The reviewer-re-review body is
only used after an explicit inspection of the post-review
diff + in-thread replies confirms the feedback has been
addressed in code or explained away. The previous logic
(which switched on whether the author had @-mentioned the
reviewer) put the re-review request on the reviewer's desk
even when the actual work was still on the author's side.
Updates classify.md, suggested-actions.md, actions.md,
comment-templates.md, SKILL.md, and interaction-loop.md so the
group ordering, data requirements, and body-template decision
are consistent across the skill.
* pr-triage: never suggest rebase on CONFLICTING PRs — route to draft
Empirically every rebase attempted on a PR whose mergeable state
is CONFLICTING came back with "Cannot update PR branch due to
conflicts". GitHub's update-branch endpoint does a side-merge
of the base branch into the PR head; when the merge doesn't
apply cleanly, it refuses, and retrying burns round-trips
without progress. The fix is to stop suggesting rebase in that
state at all — those PRs go straight to draft with the
merge-conflicts violation so the author is pointed at the
local-rebase instructions in the comment body.
- suggested-actions.md: the "mergeable == CONFLICTING" rule now
maps to draft regardless of other signals. An explicit hard
rule spells out why.
- actions.md#rebase: a mergeable check runs before the
update-branch call; if the state is CONFLICTING the action
refuses with a route-to-draft hint. If a non-CONFLICTING call
still 422s, the skill does not retry — it falls through to
draft.
- SKILL.md Step 3 table updated to reflect the new mapping.
* pr-triage: tighten untriaged-draft stale threshold from 3 weeks to 2 weeks
Drafts that have had no activity for 14 days (was 21) now fall into
Sweep 1b (untriaged-draft close). The triaged-draft 7-day threshold
for Sweep 1a is unchanged.
Maintainer preference: two weeks is enough signal that a draft has
stalled; waiting the extra week was leaving queue pressure without
adding useful context on author intent.
* pr-triage: stale-Copilot threshold 14 days -> 7 days, soften body
Two related changes for the stale_copilot_review classification:
- Tighten the trigger threshold. Copilot reviews that sit unaddressed
for a week already signal a stalled PR — waiting two weeks before
drafting adds queue pressure without useful signal.
- Revise the draft-comment language to explicitly call out that some
Copilot suggestions may be incorrect or irrelevant, and that it is
still the author's responsibility to respond — apply the fix, reply
in-thread explaining why it does not apply, or resolve the thread
if the feedback is no longer relevant. Previously the wording could
be read as 'please do everything Copilot said', which is the wrong
bar.
* pr-triage: make action_required REST check primary for pending_workflow_approval
A PR that has real CI runs held in action_required for approval
can still report statusCheckRollup.state == SUCCESS, because the
rollup aggregates only completed check-runs and fast bot checks
(Mergeable, WIP, DCO, boring-cyborg) succeed unconditionally
before the real CI is even allowed to start. Trusting the rollup
classifies such a PR as passing and leads to premature mark-ready.
Changes:
- classify.md: rewrite C1 (pending_workflow_approval) so the
repo-level REST call GET /repos/.../actions/runs?status=action_required
is the primary signal, not a fallback. Index the response by
head_sha once per page. Call out that the rollup-based check
alone is not sufficient and explain why.
- classify.md: rewrite 'Verifying real CI ran' from an optional
note into a mandatory pre-passing guard. Expand the real-CI
pattern list to include Tests (exact), CodeQL, and
'Check newsfragment PR number'.
- fetch-and-batch.md: add an 'Mandatory: action_required run
index per page' section that documents the REST call as part of
the per-page fetch plan (one extra round-trip per page, well
inside the budget).
* pr-triage: spell out author responsibility to mark threads resolved
The Unresolved review comments / Unaddressed Copilot review violation
bodies now explicitly state that it is the author's responsibility to
mark a thread as resolved once they believe it has been addressed —
whether that was by pushing a fix or by replying with an explanation
of why the suggestion doesn't apply.
Reviewers do not auto-close their own threads, so a thread that is
addressed but left unresolved reads as 'still waiting on the author'
and blocks the PR from moving forward. Making this explicit in the
draft comment is the difference between first-time contributors
wondering why their PR still looks blocked after a fix vs. knowing
to click 'Resolve conversation' at the bottom of each thread.
* pr-triage: mandatory pre-check against action_required on mark-ready
Sole purpose of this commit is to add an executable guard in
actions.md that the classifier's real-CI-ran check cannot
substitute for. Empirically, the classifier can still green-light
a PR that has pending workflow approvals if the GraphQL batch
fetch was taken before GitHub indexed a freshly-required workflow
run, or if only the bot subset of checks has completed and the
classifier's 30-context sample missed a real-CI entry.
Changes:
- actions.md §mark-ready: add a MUST-DO pre-mutation check —
GET /repos/<owner>/<repo>/actions/runs?head_sha=<SHA>&status=
action_required returning any result is a hard refuse. On
refuse, reclassify the PR as pending_workflow_approval and
route accordingly instead of silently dropping the mutation.
- SKILL.md Golden rules: add rule 1b elevating the check to the
top-of-file contract so a skill implementor can't miss it.
The rationale (fast bot checks finish first while Tests /
CodeQL / newsfragment sit in action_required) is spelled out
so nobody thinks this is belt-and-braces redundancy.
* pr-triage: add AI-attribution footer to contributor comments
Every contributor-facing triage comment now ends with a short
footer that (a) notes the comment was drafted by an AI-assisted
tool and may contain mistakes, (b) reassures the contributor
that a human maintainer will take the next look once they
address the feedback, and (c) links to a new section in the
maintainer-triage contributing doc that explains why the first
pass is automated — to free scarce maintainer time for the
conversation with contributors rather than mechanical queue
sweeping.
The footer is defined once in comment-templates.md as
<ai_attribution_footer> and referenced from every
contributor-facing template (draft, comment-only, close,
review-nudge, reviewer-ping, stale-draft-close,
inactive-to-draft, stale-workflow-approval). The
suspicious-changes template is intentionally excluded — it is
terse and already directs the contributor to maintainers on
Slack, and adding the footer would dilute the signal.
SKILL.md carries a new Golden rule 8 capturing the requirement
and the link to the rationale anchor.
(cherry picked from commit 0ed3e73)
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:dev-toolschangelog:skipChanges that should be skipped from the changelog (CI, tests, etc..)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@potiuk@vatsrahul1001