This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow-steward.git
The following commit(s) were added to refs/heads/main by this push:
new 1a89b79 feat(pr-management-triage): add docs/spellcheck to
static_check + optimistic-lock approve-workflow (#116)
1a89b79 is described below
commit 1a89b799752cba65f4e412a067b8ea50ac12007e
Author: Jarek Potiuk <[email protected]>
AuthorDate: Mon May 11 12:30:18 2026 +0200
feat(pr-management-triage): add docs/spellcheck to static_check +
optimistic-lock approve-workflow (#116)
Two unrelated-but-small classifier-accuracy improvements, both
prompted by misclassifications hit during a triage sweep on
apache/airflow:
1. classify-and-act.md: append `spellcheck`, `spelling`,
`build documentation`, `build docs`, `build-docs` to the
`static_check` substring list. A docs-build / spellcheck
failure is symmetric with the other static checks — the
contributor introduced text the checker doesn't accept and
the fix is a code change. Without these patterns, row 13
(`rerun`) fires on a single docs-build failure and the bot
sends a useless rerun request that fails identically.
2. actions.md: apply the Golden Rule 1b optimistic-lock pattern
to `approve-workflow`. Re-list pending runs at action time;
exit cleanly with a one-line note if empty (already approved
between fetch and act). Matches what `mark-ready` and
`mark-ready-with-ping` already do.
---
.claude/skills/pr-management-triage/actions.md | 39 ++++++++++++++++++----
.../pr-management-triage/classify-and-act.md | 12 ++++++-
2 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/.claude/skills/pr-management-triage/actions.md
b/.claude/skills/pr-management-triage/actions.md
index fa94b23..0dedf26 100644
--- a/.claude/skills/pr-management-triage/actions.md
+++ b/.claude/skills/pr-management-triage/actions.md
@@ -442,20 +442,45 @@ responsibility is clearly on the author.
Two steps. **Inspect the diff first** — see
[`workflow-approval.md`](workflow-approval.md) for the safety
protocol. Only after the maintainer confirms the diff looks
-non-malicious, approve:
+non-malicious, **re-list the pending runs at action time** (the
+per-page `action_required` index built during fetch may be stale
+— another maintainer may have approved between fetch and now —
+and the optimistic-lock pattern below catches the no-op race
+without burning a useless mutation):
```bash
-# List pending workflow runs for this PR.
+# Re-list pending workflow runs for this PR at action time.
# Runs awaiting approval are returned as `status: "completed"` with
# `conclusion: "action_required"` — `?status=action_required` matches
# none of them. Post-filter on `conclusion` to enumerate the real set.
-gh api "repos/<owner>/<repo>/actions/runs?head_sha=<head_sha>&per_page=20" \
- --jq '.workflow_runs[] | select(.conclusion == "action_required") | .id' |
- while read run_id; do
- gh api -X POST "repos/<owner>/<repo>/actions/runs/${run_id}/approve"
- done
+ids=$(gh api
"repos/<owner>/<repo>/actions/runs?head_sha=<head_sha>&per_page=20" \
+ --jq '.workflow_runs[] | select(.conclusion == "action_required") |
.id')
+
+if [ -z "$ids" ]; then
+ # Race: pending runs were approved between fetch and now (another
+ # maintainer, or auto-approval). Skip silently — the desired state
+ # ("CI is allowed to run for this contributor") is already true.
+ # Surface a one-line note to the maintainer so the no-op is visible.
+ echo "approve-workflow: no pending runs found at <head_sha> — already
approved by someone else" >&2
+ exit 0
+fi
+
+while read -r run_id; do
+ [ -z "$run_id" ] && continue
+ gh api -X POST "repos/<owner>/<repo>/actions/runs/${run_id}/approve"
+done <<< "$ids"
```
+The optimistic-lock pattern is the same one
+[`mark-ready`](#mark-ready--add-ready-for-maintainer-review-label)
+uses (Golden rule 1b in [`SKILL.md`](SKILL.md)) — read the
+authoritative state immediately before mutating, exit cleanly
+if the desired state is already in place. Without it, a sweep
+that classified at T0 and acts at T0 + minutes (after the
+maintainer reviewed the diff) silently surfaces "exit=0, out=
+empty" with no guidance on whether the approval landed or
+nothing was there to approve in the first place.
+
No comment is posted for `approve-workflow`. Approval is
invisible to the contributor except for CI now running, which
is what they wanted.
diff --git a/.claude/skills/pr-management-triage/classify-and-act.md
b/.claude/skills/pr-management-triage/classify-and-act.md
index d42aae2..c425271 100644
--- a/.claude/skills/pr-management-triage/classify-and-act.md
+++ b/.claude/skills/pr-management-triage/classify-and-act.md
@@ -241,10 +241,20 @@ after that timestamp.
Failed check name (case-insensitive substring match either
direction) hits one of: `static check`, `pre-commit`, `lint`,
`mypy`, `ruff`, `black`, `flake8`, `pylint`, `isort`, `bandit`,
-`codespell`, `yamllint`, `shellcheck`.
+`codespell`, `yamllint`, `shellcheck`, `spellcheck`,
+`spelling`, `build documentation`, `build docs`, `build-docs`.
Additional patterns may be configured in
`<project-config>/pr-management-triage-ci-check-map.md`.
+The doc-build / spellcheck patterns are included in the
+framework defaults because the failure mode is symmetric with
+the other static checks: the contributor introduced text the
+checker doesn't accept (a misspelled word, a broken docs
+include, a missing sphinx reference) and the fix is a code
+change, not a CI rerun. Without these patterns row 13 (`rerun`)
+fires on a single docs failure and the bot sends a useless
+rerun request that fails identically.
+
### `recent_main_failures`
Cached set of failing check names from the most recent 10