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 a8c9eab  triage: history-based @-mention routing replaces 
scope-default (#150)
a8c9eab is described below

commit a8c9eab9a322fe30d016d34f3b44ece1905317e9
Author: Jarek Potiuk <[email protected]>
AuthorDate: Thu May 14 13:05:42 2026 +0200

    triage: history-based @-mention routing replaces scope-default (#150)
    
    Replaces the existing scope-based @-mention routing in
    security-issue-triage with a history-based priority order:
    
      1. PR-author of the analogous prior fix (via gh search prs)
      2. Recent reviewer of the area (via gh pr list reviewed-by)
      3. Scope-default fallback (existing behavior, narrowed to 1 pick)
    
    The routing decision is cached per unique code area within a
    bulk-mode run so a 5-tracker sweep through one directory issues
    one set of gh search prs queries, not five.
    
    Adds an explicit routing-failure fallback: when no PR-history
    match exists for a code area, the skill stops and surfaces a
    "confirm @-mentions before posting" prompt rather than silently
    defaulting to a generic roster ping.
    
    Motivation: scope-default routing produces generic 3-person pings
    that the team trains itself to ignore. For airflow-s#406 (missing
    ti:self enforcement on /execution/task-reschedules) the right
    pick was unambiguous — @amoghrajesh wrote apache/airflow#66071
    introducing the mechanism — but the existing scope-default rule
    produced a generic providers ping. This PR codifies the priority
    order so the classifier reaches the same answer the human triager
    reaches by hand.
    
    Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
---
 .claude/skills/security-issue-triage/SKILL.md | 91 +++++++++++++++++++++------
 1 file changed, 72 insertions(+), 19 deletions(-)

diff --git a/.claude/skills/security-issue-triage/SKILL.md 
b/.claude/skills/security-issue-triage/SKILL.md
index b99a616..1f35ba0 100644
--- a/.claude/skills/security-issue-triage/SKILL.md
+++ b/.claude/skills/security-issue-triage/SKILL.md
@@ -524,25 +524,78 @@ people are best placed to answer>?
 
 ### `@`-mention routing
 
-The skill picks **2-3 security-team handles** per comment from
-the roster cached in Step 0. The picking heuristic:
-
-1. **Scope-based** — scope `airflow` (core) routes to the core
-   security-team subset; scope `providers` routes to the
-   providers maintainers on the security team; scope `chart`
-   routes to the chart maintainers. The project's
-   `release-trains.md` lists these subsets.
-2. **Topic-specific override** — if a tracker is a variant of
-   a recently-closed CVE, also tag the `@`-handle of whoever
-   owned that CVE's fix PR (the topic-specific person has the
-   richest context).
-3. **Never tag the triager themselves** — the skill is invoked
-   by a security-team member; tagging them in their own comment
-   is noise. Drop their handle from the routing set before
-   composition.
-4. **Never tag the entire roster** — 12+ handles on every
-   triage comment trains the team to ignore the pings. Cap at
-   3 per comment, pick by relevance.
+The skill picks **1-3 security-team handles** per comment from
+the roster cached in Step 0. Priority order, applied
+mechanically:
+
+1. **PR-author of the analogous prior fix.** For each tracker,
+   extract the code pointers (file paths, function names) from
+   Step 2. For each pointer, run:
+
+   ```bash
+   gh search prs --repo <upstream> --json author,title,mergedAt,url \
+     -- <pointer> security
+   gh search prs --repo <upstream> --json author,title,mergedAt,url \
+     -- <pointer> fix
+   ```
+
+   The most-recent matching PR's author is the **#1 pick** — they
+   have the deepest current context. Cross-check against the
+   security-team roster cached in Step 0; drop if not on the
+   roster. If multiple PRs are recent, pick the one with the
+   tightest title-match on the tracker's vulnerability class
+   (e.g. "auth" / "deserialize" / "path traversal").
+
+2. **Recent reviewer of the area.** For the same code pointer,
+   find roster members who have reviewed recent PRs:
+
+   ```bash
+   gh pr list --repo <upstream> --search 'reviewed-by:<handle>' \
+     --json files,reviews,mergedAt -- <pointer>
+   ```
+
+   Iterate the roster (cached in Step 0); the roster member with
+   the most-recent review in the area is the **#2 pick**.
+
+3. **Scope-default fallback.** Only if 1 and 2 yield nothing,
+   fall back to the scope-based subset from
+   
[`<project-config>/release-trains.md`](../../../<project-config>/release-trains.md).
+   Pick **1 person**, not 3 — a single targeted ping outperforms
+   a roster sweep. The project may declare per-scope expertise
+   hints under a "Security team area-of-expertise hints"
+   subsection of `release-trains.md`; honour those when present
+   but do not require them.
+
+**Cache the routing decision per code area** within the run —
+if 5 trackers all touch `airflow/api_fastapi/execution_api/`,
+the @-mention set is identical for all 5 (computed once,
+re-used).
+
+**Cap at 3 handles per comment**, prefer 2. The triager (cached
+in Step 0 as `viewer_login`) is automatically excluded.
+
+**Topic-specific override** (still applies on top of the above):
+if a tracker is a variant of a recently-closed CVE, also tag
+the `@`-handle of whoever owned that CVE's fix PR (the
+topic-specific person has the richest context). Cap still
+applies; if topic-specific puts you at the cap, drop the
+scope-default fallback.
+
+**Never tag the entire roster.** 12+ handles on every triage
+comment trains the team to ignore the pings. If routing returns
+more than 3 candidates, the cap forces a prioritised pick.
+
+**Routing-failure fallback.** If the `gh search prs` queries
+return nothing (new code area, no prior PRs), the skill stops
+and surfaces *"no PR-history match for `<pointer>`; falling
+back to scope-default — please confirm @-mentions before
+posting"*. The user types the corrected handle(s) into the
+proposal; the skill caches the decision for the rest of the
+run so the same fallback doesn't recur on every tracker.
+
+**Budget**: ≤ 2 `gh search prs` calls per unique code area
+(across all trackers in a bulk run, post-caching). The cache
+makes this trivially cheap even on large sweeps.
 
 The roster source-of-truth is
 
[`<project-config>/release-trains.md`](../../../<project-config>/release-trains.md);

Reply via email to