From c07a76c20be3466f58c5044adf58d6003b5f93b1 Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Sun, 3 May 2026 14:20:31 +0200 Subject: [PATCH] refactor(skills): rename to type-what_you_operate_on-action convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standardise the 17 skill folder names + 4 adopter-config scaffold files on `type-what_you_operate_on-action` for consistency and to make the responsible noun + verb visible at a glance. Setup family — `setup-{thing}-{action}`: setup-secure-config → setup-isolated-setup-install setup-verify-secure-config → setup-isolated-setup-verify setup-update-secure-config → setup-isolated-setup-update setup-upgrade-steward → setup-steward-upgrade setup-verify-steward → setup-steward-verify setup-sync-shared-config → setup-shared-config-sync (`secure-config` becomes `isolated-setup` to more accurately name what is being installed — an isolated agent setup, not just a secure config.) Security family — `security-{issue,cve}-{action}`, singular noun: security-import-issues → security-issue-import security-import-issues-from-md → security-issue-import-from-md security-import-issue-from-pr → security-issue-import-from-pr security-sync-issues → security-issue-sync security-fix-issue → security-issue-fix security-allocate-cve → security-cve-allocate security-deduplicate-issues → security-issue-deduplicate security-invalidate-issue → security-issue-invalidate PR family — `pr-management-{action}` (type prefix promoted from plain `pr-` to `pr-management-` to disambiguate from `pr` as an enum value elsewhere): pr-triage → pr-management-triage pr-stats → pr-management-stats pr-maintainer-review → pr-management-code-review Adopter-config scaffolds renamed to match: pr-triage-config.md → pr-management-config.md pr-triage-comment-templates.md → pr-management-triage-comment-templates.md pr-triage-ci-check-map.md → pr-management-triage-ci-check-map.md pr-maintainer-review-criteria.md → pr-management-code-review-criteria.md 62 files touched, 488/488 ins/del — pure rename. Cross-references updated everywhere (README, AGENTS.md, CONTRIBUTING.md, secure-agent-setup.md, secure-agent-internals.md, projects/_template/, .claude/skills/*/, tools/, generate-cve-json docstrings). doctoc TOCs regenerated. Generated-by: Claude Code (Claude Opus 4.7) --- .../SKILL.md | 50 +++--- .../adversarial.md | 2 +- .../criteria.md | 0 .../posting.md | 0 .../prerequisites.md | 2 +- .../review-flow.md | 0 .../selectors.md | 6 +- .../SKILL.md | 34 ++--- .../aggregate.md | 2 +- .../classify.md | 6 +- .../fetch.md | 10 +- .../render.md | 6 +- .../SKILL.md | 16 +- .../actions.md | 0 .../classify-and-act.md | 0 .../comment-templates.md | 0 .../fetch-and-batch.md | 2 +- .../interaction-loop.md | 0 .../prerequisites.md | 2 +- .../rationale.md | 0 .../stale-sweeps.md | 0 .../workflow-approval.md | 0 .../SKILL.md | 38 ++--- .../SKILL.md | 24 +-- .../SKILL.md | 22 +-- .../SKILL.md | 26 ++-- .../SKILL.md | 42 ++--- .../SKILL.md | 28 ++-- .../SKILL.md | 28 ++-- .../SKILL.md | 28 ++-- .../SKILL.md | 16 +- .../SKILL.md | 14 +- .../SKILL.md | 16 +- .../SKILL.md | 6 +- .../SKILL.md | 22 +-- .../SKILL.md | 16 +- AGENTS.md | 40 ++--- CONTRIBUTING.md | 18 +-- README.md | 144 +++++++++--------- how-to-fix-a-security-issue.md | 10 +- new-members-onboarding.md | 4 +- projects/_template/README.md | 28 ++-- projects/_template/canned-responses.md | 16 +- projects/_template/fix-workflow.md | 6 +- projects/_template/milestones.md | 4 +- ... => pr-management-code-review-criteria.md} | 6 +- ...iage-config.md => pr-management-config.md} | 12 +- ...d => pr-management-triage-ci-check-map.md} | 6 +- ...pr-management-triage-comment-templates.md} | 16 +- projects/_template/scope-labels.md | 2 +- projects/_template/title-normalization.md | 4 +- secure-agent-internals.md | 2 +- secure-agent-setup.md | 24 +-- tools/cve-org/tool.md | 4 +- tools/github/issue-template.md | 6 +- tools/github/labels.md | 4 +- tools/github/project-board.md | 4 +- tools/github/status-rollup.md | 30 ++-- tools/gmail/asf-relay.md | 2 +- tools/gmail/draft-backends.md | 4 +- tools/gmail/operations.md | 6 +- tools/gmail/ponymail-archive.md | 8 +- tools/gmail/search-queries.md | 20 +-- tools/gmail/tool.md | 2 +- tools/ponymail/operations.md | 2 +- tools/vulnogram/allocation.md | 12 +- tools/vulnogram/generate-cve-json/SKILL.md | 20 +-- .../src/generate_cve_json/cve_json.py | 6 +- tools/vulnogram/record.md | 16 +- .../release-manager-handoff-comment.md | 10 +- .../release-manager-publication-comment.md | 4 +- tools/vulnogram/tool.md | 4 +- 72 files changed, 485 insertions(+), 485 deletions(-) rename .claude/skills/{pr-maintainer-review => pr-management-code-review}/SKILL.md (92%) rename .claude/skills/{pr-maintainer-review => pr-management-code-review}/adversarial.md (99%) rename .claude/skills/{pr-maintainer-review => pr-management-code-review}/criteria.md (100%) rename .claude/skills/{pr-maintainer-review => pr-management-code-review}/posting.md (100%) rename .claude/skills/{pr-maintainer-review => pr-management-code-review}/prerequisites.md (98%) rename .claude/skills/{pr-maintainer-review => pr-management-code-review}/review-flow.md (100%) rename .claude/skills/{pr-maintainer-review => pr-management-code-review}/selectors.md (98%) rename .claude/skills/{pr-stats => pr-management-stats}/SKILL.md (75%) rename .claude/skills/{pr-stats => pr-management-stats}/aggregate.md (95%) rename .claude/skills/{pr-stats => pr-management-stats}/classify.md (90%) rename .claude/skills/{pr-stats => pr-management-stats}/fetch.md (94%) rename .claude/skills/{pr-stats => pr-management-stats}/render.md (96%) rename .claude/skills/{pr-triage => pr-management-triage}/SKILL.md (95%) rename .claude/skills/{pr-triage => pr-management-triage}/actions.md (100%) rename .claude/skills/{pr-triage => pr-management-triage}/classify-and-act.md (100%) rename .claude/skills/{pr-triage => pr-management-triage}/comment-templates.md (100%) rename .claude/skills/{pr-triage => pr-management-triage}/fetch-and-batch.md (99%) rename .claude/skills/{pr-triage => pr-management-triage}/interaction-loop.md (100%) rename .claude/skills/{pr-triage => pr-management-triage}/prerequisites.md (98%) rename .claude/skills/{pr-triage => pr-management-triage}/rationale.md (100%) rename .claude/skills/{pr-triage => pr-management-triage}/stale-sweeps.md (100%) rename .claude/skills/{pr-triage => pr-management-triage}/workflow-approval.md (100%) rename .claude/skills/{security-allocate-cve => security-cve-allocate}/SKILL.md (96%) rename .claude/skills/{security-deduplicate-issues => security-issue-deduplicate}/SKILL.md (96%) rename .claude/skills/{security-fix-issue => security-issue-fix}/SKILL.md (97%) rename .claude/skills/{security-import-issues-from-md => security-issue-import-from-md}/SKILL.md (96%) rename .claude/skills/{security-import-issue-from-pr => security-issue-import-from-pr}/SKILL.md (94%) rename .claude/skills/{security-import-issues => security-issue-import}/SKILL.md (97%) rename .claude/skills/{security-invalidate-issue => security-issue-invalidate}/SKILL.md (96%) rename .claude/skills/{security-sync-issues => security-issue-sync}/SKILL.md (99%) rename .claude/skills/{setup-secure-config => setup-isolated-setup-install}/SKILL.md (92%) rename .claude/skills/{setup-update-secure-config => setup-isolated-setup-update}/SKILL.md (94%) rename .claude/skills/{setup-verify-secure-config => setup-isolated-setup-verify}/SKILL.md (92%) rename .claude/skills/{setup-sync-shared-config => setup-shared-config-sync}/SKILL.md (98%) rename .claude/skills/{setup-upgrade-steward => setup-steward-upgrade}/SKILL.md (93%) rename .claude/skills/{setup-verify-steward => setup-steward-verify}/SKILL.md (95%) rename projects/_template/{pr-maintainer-review-criteria.md => pr-management-code-review-criteria.md} (93%) rename projects/_template/{pr-triage-config.md => pr-management-config.md} (81%) rename projects/_template/{pr-triage-ci-check-map.md => pr-management-triage-ci-check-map.md} (90%) rename projects/_template/{pr-triage-comment-templates.md => pr-management-triage-comment-templates.md} (85%) diff --git a/.claude/skills/pr-maintainer-review/SKILL.md b/.claude/skills/pr-management-code-review/SKILL.md similarity index 92% rename from .claude/skills/pr-maintainer-review/SKILL.md rename to .claude/skills/pr-management-code-review/SKILL.md index 4b83e22b..71f8c8d1 100644 --- a/.claude/skills/pr-maintainer-review/SKILL.md +++ b/.claude/skills/pr-management-code-review/SKILL.md @@ -15,7 +15,7 @@ description: | when_to_use: | Invoke when a maintainer says "review my PRs", "go through the PRs assigned to me", "review my queue", "review the area:scheduler PRs", "review PR NNN", "do my review pass", or any variation on "look over the code on PRs I'm - responsible for, one at a time." Distinct from `pr-triage`, which decides *whether* to engage with a PR. This skill is + responsible for, one at a time." Distinct from `pr-management-triage`, which decides *whether* to engage with a PR. This skill is invoked **after** triage has produced PRs marked `ready for maintainer review` (or any other curated selector) and a human reviewer is doing the actual code review. license: Apache-2.0 @@ -39,7 +39,7 @@ two questions per PR: > *If not, what specifically should change before it lands?* It is the review-bench counterpart to -[`pr-triage`](../pr-triage/SKILL.md). Triage decides whether to +[`pr-management-triage`](../pr-management-triage/SKILL.md). Triage decides whether to *engage* with a PR (draft / comment / close / rebase / rerun / mark-ready / ping). This skill takes PRs that have already cleared triage (or any other curated selector) and produces an @@ -65,14 +65,14 @@ Detail files in this directory break the logic out topic-by-topic: This skill resolves project-specific content from the adopter's `/` directory: -- [`/pr-maintainer-review-criteria.md`](../../../projects/_template/pr-maintainer-review-criteria.md) — list of the project's review-criteria source files (repo-wide AGENTS.md, code-review docs, per-area AGENTS.md), security-model calibration doc, backport-branch pattern, and section-anchor URLs the framework links per finding. +- [`/pr-management-code-review-criteria.md`](../../../projects/_template/pr-management-code-review-criteria.md) — list of the project's review-criteria source files (repo-wide AGENTS.md, code-review docs, per-area AGENTS.md), security-model calibration doc, backport-branch pattern, and section-anchor URLs the framework links per finding. The framework's [`criteria.md`](criteria.md) currently embeds airflow's source-file paths inline as the default. Follow-up work will move them out so the skill reads exclusively from the adopter config — until then, non-airflow adopters override by forking [`criteria.md`](criteria.md) into their own -`.claude/skills/pr-maintainer-review/`. +`.claude/skills/pr-management-code-review/`. --- @@ -181,11 +181,11 @@ check rollup; see [`prerequisites.md#ci-precheck`](prerequisites.md). **Golden rule 9 — out of scope: triage actions.** This skill does not convert PRs to draft, close them, rebase them, ping reviewers, or rerun CI. Those are -[`pr-triage`](../pr-triage/SKILL.md) actions. If the maintainer +[`pr-management-triage`](../pr-management-triage/SKILL.md) actions. If the maintainer discovers during review that a PR needs a triage action (e.g. it should really be drafted because of merge conflicts that appeared), the skill says so explicitly and points them at -`/pr-triage pr:`. It does not silently invoke triage actions. +`/pr-management-triage pr:`. It does not silently invoke triage actions. **Golden rule 10 — every PR number is rendered as its full URL.** A bare `#65981` is unclickable in most terminals; the @@ -246,7 +246,7 @@ headline-confirm gate anyway). Before running, resolve the maintainer's selector into a concrete query. -The **default selector** — what `/pr-maintainer-review` with no +The **default selector** — what `/pr-management-code-review` with no arguments resolves to — is the working list called **"my reviews"**: every open PR on `` that matches at least one of the five signals below, all rooted on @@ -306,26 +306,26 @@ labels (the skill warns and degrades gracefully — see ## How to invoke — examples -The slash command is `/pr-maintainer-review`. A few worked +The slash command is `/pr-management-code-review`. A few worked examples a maintainer can paste: | Goal | Invocation | |---|---| -| Walk through everything in **"my reviews"**, newest first | `/pr-maintainer-review` | -| Review a single PR (the most common ad-hoc trigger) | `/pr-maintainer-review pr:65981` | -| Just the PRs where I'm a CODEOWNER, ignore the rest | `/pr-maintainer-review codeowner-only` | -| PRs that explicitly `@`-mention me, skip the noise | `/pr-maintainer-review mentioned-only` | -| Re-look at the PRs I already reviewed (follow-ups after author push) | `/pr-maintainer-review reviewed-before-only` | -| My-reviews **but** drop touching-mine (too noisy this morning) | `/pr-maintainer-review no-touching-mine` | -| My-reviews limited to scheduler-area, max 5 | `/pr-maintainer-review area:scheduler max:5` | -| My-reviews scoped to non-collaborator authors (extra-careful pass) | `/pr-maintainer-review collab:false` | -| The team queue (PRs where `-providers-amazon` is requested) | `/pr-maintainer-review team:airflow-providers-amazon` | -| The wider curated queue triage already promoted | `/pr-maintainer-review ready` | -| Stay body-only this session (no inline picker) | `/pr-maintainer-review inline:off` | -| Dry-run the queue — draft everything, post nothing | `/pr-maintainer-review dry-run` | -| Same, against a different repo | `/pr-maintainer-review dry-run repo:-site` | -| Pair with an adversarial reviewer for a second read on each PR | `/pr-maintainer-review with-reviewer:/codex-plugin:adversarial-review` | -| Skip background analysis subagents (tiny queue, prefetch is wasted) | `/pr-maintainer-review max:1 no-prefetch` | +| Walk through everything in **"my reviews"**, newest first | `/pr-management-code-review` | +| Review a single PR (the most common ad-hoc trigger) | `/pr-management-code-review pr:65981` | +| Just the PRs where I'm a CODEOWNER, ignore the rest | `/pr-management-code-review codeowner-only` | +| PRs that explicitly `@`-mention me, skip the noise | `/pr-management-code-review mentioned-only` | +| Re-look at the PRs I already reviewed (follow-ups after author push) | `/pr-management-code-review reviewed-before-only` | +| My-reviews **but** drop touching-mine (too noisy this morning) | `/pr-management-code-review no-touching-mine` | +| My-reviews limited to scheduler-area, max 5 | `/pr-management-code-review area:scheduler max:5` | +| My-reviews scoped to non-collaborator authors (extra-careful pass) | `/pr-management-code-review collab:false` | +| The team queue (PRs where `-providers-amazon` is requested) | `/pr-management-code-review team:airflow-providers-amazon` | +| The wider curated queue triage already promoted | `/pr-management-code-review ready` | +| Stay body-only this session (no inline picker) | `/pr-management-code-review inline:off` | +| Dry-run the queue — draft everything, post nothing | `/pr-management-code-review dry-run` | +| Same, against a different repo | `/pr-management-code-review dry-run repo:-site` | +| Pair with an adversarial reviewer for a second read on each PR | `/pr-management-code-review with-reviewer:/codex-plugin:adversarial-review` | +| Skip background analysis subagents (tiny queue, prefetch is wasted) | `/pr-management-code-review max:1 no-prefetch` | Selectors compose freely. Most flags carry through cleanly: `area:scheduler reviewed-before-only since:7d` is "PRs in @@ -475,9 +475,9 @@ writes a session log to disk. - **First-pass triage actions.** Drafting, closing, rebasing, pinging, rerunning CI, marking `ready for maintainer review` — - all live in [`pr-triage`](../pr-triage/SKILL.md). If the + all live in [`pr-management-triage`](../pr-management-triage/SKILL.md). If the current PR needs one of those, the skill says so and points - at `/pr-triage pr:`. + at `/pr-management-triage pr:`. - **Merging.** Merging is a conscious maintainer action that belongs in a separate flow. - **Submitting reviews on closed / merged PRs.** The skill only diff --git a/.claude/skills/pr-maintainer-review/adversarial.md b/.claude/skills/pr-management-code-review/adversarial.md similarity index 99% rename from .claude/skills/pr-maintainer-review/adversarial.md rename to .claude/skills/pr-management-code-review/adversarial.md index a88ab255..0062f7c8 100644 --- a/.claude/skills/pr-maintainer-review/adversarial.md +++ b/.claude/skills/pr-management-code-review/adversarial.md @@ -34,7 +34,7 @@ Pass the slash command to invoke as the `with-reviewer:` selector: ```text -/pr-maintainer-review with-reviewer:/some-plugin:adversarial-review +/pr-management-code-review with-reviewer:/some-plugin:adversarial-review ``` The skill stores that command for the session and proposes it diff --git a/.claude/skills/pr-maintainer-review/criteria.md b/.claude/skills/pr-management-code-review/criteria.md similarity index 100% rename from .claude/skills/pr-maintainer-review/criteria.md rename to .claude/skills/pr-management-code-review/criteria.md diff --git a/.claude/skills/pr-maintainer-review/posting.md b/.claude/skills/pr-management-code-review/posting.md similarity index 100% rename from .claude/skills/pr-maintainer-review/posting.md rename to .claude/skills/pr-management-code-review/posting.md diff --git a/.claude/skills/pr-maintainer-review/prerequisites.md b/.claude/skills/pr-management-code-review/prerequisites.md similarity index 98% rename from .claude/skills/pr-maintainer-review/prerequisites.md rename to .claude/skills/pr-management-code-review/prerequisites.md index 05a345ae..54784ba5 100644 --- a/.claude/skills/pr-maintainer-review/prerequisites.md +++ b/.claude/skills/pr-management-code-review/prerequisites.md @@ -143,7 +143,7 @@ a separate call. The state is one of: `SKILL.md`, `APPROVE` is off the table; downgrade to `COMMENT` or `REQUEST_CHANGES`. - `EXPECTED` (workflow approval pending) — surface explicitly - and recommend `/pr-triage pr:` for the workflow-approval + and recommend `/pr-management-triage pr:` for the workflow-approval flow first; do not attempt to review the PR until CI has actually run. diff --git a/.claude/skills/pr-maintainer-review/review-flow.md b/.claude/skills/pr-management-code-review/review-flow.md similarity index 100% rename from .claude/skills/pr-maintainer-review/review-flow.md rename to .claude/skills/pr-management-code-review/review-flow.md diff --git a/.claude/skills/pr-maintainer-review/selectors.md b/.claude/skills/pr-management-code-review/selectors.md similarity index 98% rename from .claude/skills/pr-maintainer-review/selectors.md rename to .claude/skills/pr-management-code-review/selectors.md index 7716da21..0637b9ae 100644 --- a/.claude/skills/pr-maintainer-review/selectors.md +++ b/.claude/skills/pr-management-code-review/selectors.md @@ -42,7 +42,7 @@ default working list — referred to throughout the docs as PRs that already have a `gh pr review`-submitted review from `` (state `APPROVED`, `CHANGES_REQUESTED`, or `COMMENTED`). **Triage comments do not count** — the - `pr-triage` skill's PR-conversation comments live in + `pr-management-triage` skill's PR-conversation comments live in `comments[]`, never in `reviews[]`, so they are excluded automatically. See [`reviewed-before`](#reviewed-before--prs-i-already-reviewed) @@ -337,7 +337,7 @@ A PR is **reviewed-before by ``** if its `reviews[]` array contains any entry with `author.login == `, regardless of `state`. -**Triage comments do NOT count.** The `pr-triage` skill posts +**Triage comments do NOT count.** The `pr-management-triage` skill posts its notes via `gh pr comment`, which lands in the PR's `comments` array (the GitHub *issue-comment* endpoint). Those never appear in `reviews`. So the reviewed-before filter @@ -545,7 +545,7 @@ why the assistant proposes but does not invoke. Example: ```text -/pr-maintainer-review with-reviewer:/some-plugin:adversarial-review +/pr-management-code-review with-reviewer:/some-plugin:adversarial-review ``` If `with-reviewer:` is not passed, the skill checks the diff --git a/.claude/skills/pr-stats/SKILL.md b/.claude/skills/pr-management-stats/SKILL.md similarity index 75% rename from .claude/skills/pr-stats/SKILL.md rename to .claude/skills/pr-management-stats/SKILL.md index cc94bac7..657e3f61 100644 --- a/.claude/skills/pr-stats/SKILL.md +++ b/.claude/skills/pr-management-stats/SKILL.md @@ -1,5 +1,5 @@ --- -name: pr-stats +name: pr-management-stats description: | Produce maintainer-facing statistics about open pull requests on the configured `` repo (default: read from `/project.md → upstream_repo`). Successor to @@ -23,7 +23,7 @@ description: | → the authenticated GitHub login of the maintainer running the skill Substitute these before running any `gh` command below. --> -# pr-stats +# pr-management-stats Read-only skill that answers "what does the open-PR backlog *look* like" as two tables: @@ -33,14 +33,14 @@ Read-only skill that answers "what does the open-PR backlog | **Triaged final-state** | closed / merged PRs since a cutoff date, broken down by `area:*` label | Shows triage outcomes — what fraction of triaged PRs merged, closed, or got an author response before closing. | | **Triaged still-open** | all currently-open PRs, broken down by `area:*` label | Shows current queue pressure — triage coverage, author-response rate, ready-for-review count, age buckets. | -The skill is the statistical complement of [`pr-triage`](../pr-triage/SKILL.md) — same repo, same classification logic, no mutations. Running the two in sequence (stats → triage → stats) lets a maintainer measure a sweep's effect. +The skill is the statistical complement of [`pr-management-triage`](../pr-management-triage/SKILL.md) — same repo, same classification logic, no mutations. Running the two in sequence (stats → triage → stats) lets a maintainer measure a sweep's effect. Detail files: | File | Purpose | |---|---| | [`fetch.md`](fetch.md) | GraphQL templates for open-PR list and closed/merged-since-cutoff list. | -| [`classify.md`](classify.md) | Triage-status detection (waiting vs. responded vs. never-triaged) — reuses the `Pull Request quality criteria` marker from `pr-triage`. | +| [`classify.md`](classify.md) | Triage-status detection (waiting vs. responded vs. never-triaged) — reuses the `Pull Request quality criteria` marker from `pr-management-triage`. | | [`aggregate.md`](aggregate.md) | Area grouping, age buckets, totals, percentage rules. | | [`render.md`](render.md) | The two tables — column order, footers, header wording. | @@ -49,23 +49,23 @@ Detail files: ## Adopter configuration This skill reads the same area-label prefix and triage-marker -string declared in [`pr-triage`'s adopter config](../pr-triage/SKILL.md#adopter-configuration): +string declared in [`pr-management-triage`'s adopter config](../pr-management-triage/SKILL.md#adopter-configuration): -- [`/pr-triage-config.md → area_label_prefix`](../../../projects/_template/pr-triage-config.md) — drives the area grouping in both stats tables. -- [`/pr-triage-comment-templates.md → Triage-marker visible link text`](../../../projects/_template/pr-triage-comment-templates.md) — the literal string that classifies a PR as triaged. **Both `pr-triage` and `pr-stats` must agree** on this string; the framework defaults to `Pull Request quality criteria`. +- [`/pr-management-config.md → area_label_prefix`](../../../projects/_template/pr-management-config.md) — drives the area grouping in both stats tables. +- [`/pr-management-triage-comment-templates.md → Triage-marker visible link text`](../../../projects/_template/pr-management-triage-comment-templates.md) — the literal string that classifies a PR as triaged. **Both `pr-management-triage` and `pr-management-stats` must agree** on this string; the framework defaults to `Pull Request quality criteria`. -No `pr-stats`-specific config file is needed — the skill is -read-only and inherits everything from `pr-triage`'s contract. +No `pr-management-stats`-specific config file is needed — the skill is +read-only and inherits everything from `pr-management-triage`'s contract. --- ## Golden rules -**Golden rule 1 — no mutations, ever.** This skill only reads. It must not post comments, add labels, close, rebase, or approve anything. If the maintainer asks for stats and also wants an action, decline the mutation and redirect to `pr-triage`. +**Golden rule 1 — no mutations, ever.** This skill only reads. It must not post comments, add labels, close, rebase, or approve anything. If the maintainer asks for stats and also wants an action, decline the mutation and redirect to `pr-management-triage`. -**Golden rule 2 — reuse pr-triage's triage-detection.** The "triaged" count and "responded" count depend on the same `Pull Request quality criteria` marker string and the same collaborator set (`OWNER`/`MEMBER`/`COLLABORATOR`) that drive the triage-marker rows in `pr-triage/classify-and-act.md` (rows 3–4 — `already_triaged`). Don't invent a second definition — both skills must agree on "is this PR triaged". +**Golden rule 2 — reuse pr-management-triage's triage-detection.** The "triaged" count and "responded" count depend on the same `Pull Request quality criteria` marker string and the same collaborator set (`OWNER`/`MEMBER`/`COLLABORATOR`) that drive the triage-marker rows in `pr-management-triage/classify-and-act.md` (rows 3–4 — `already_triaged`). Don't invent a second definition — both skills must agree on "is this PR triaged". -**Golden rule 3 — one GraphQL call per batch, not per PR.** Same rule as `pr-triage/fetch-and-batch.md`. One aliased query covers the open-PR list for a whole page; the closed/merged fetch is paginated by GitHub's search cursor. Never call `gh pr view` per PR. +**Golden rule 3 — one GraphQL call per batch, not per PR.** Same rule as `pr-management-triage/fetch-and-batch.md`. One aliased query covers the open-PR list for a whole page; the closed/merged fetch is paginated by GitHub's search cursor. Never call `gh pr view` per PR. **Golden rule 4 — include a legend with every render.** The tables are dense (15+ columns on Table 2). Always print a short legend after the tables explaining the columns — `Contrib.` = non-collaborator, `Responded` = author replied after the triage comment, `Drafted by triager` = PR converted to draft by the viewer, etc. Nobody remembers column abbreviations in isolation. @@ -91,8 +91,8 @@ No per-PR drill-in — this skill is aggregate-only. ## Step 0 — Pre-flight 1. `gh auth status` must succeed; capture the viewer login (needed for the triage-marker check in step 2). -2. Run one GraphQL query that asks both for `viewer { login }` and for `repository(owner, name) { name }` to confirm the repo is reachable. `viewerPermission` is NOT required (this skill doesn't mutate) — skip the write-check that `pr-triage` does. -3. Read or initialise the scratch cache at `/tmp/pr-stats-cache-.json` (see [`aggregate.md#cache`](aggregate.md)). The cache stores the viewer login and a map of `pr_number → (head_sha, triage_status)` so a re-run inside the same session skips the per-PR enrichment. +2. Run one GraphQL query that asks both for `viewer { login }` and for `repository(owner, name) { name }` to confirm the repo is reachable. `viewerPermission` is NOT required (this skill doesn't mutate) — skip the write-check that `pr-management-triage` does. +3. Read or initialise the scratch cache at `/tmp/pr-management-stats-cache-.json` (see [`aggregate.md#cache`](aggregate.md)). The cache stores the viewer login and a map of `pr_number → (head_sha, triage_status)` so a re-run inside the same session skips the per-PR enrichment. A failure at step 1 is a **stop**. Steps 2 and 3 degrade with warnings. @@ -102,7 +102,7 @@ A failure at step 1 is a **stop**. Steps 2 and 3 degrade with warnings. Use the query template in [`fetch.md#open-prs`](fetch.md) to get every open PR with the fields needed for classification (labels, `isDraft`, `authorAssociation`, `createdAt`, last commit `committedDate`, last 10 comments for the triage-marker scan). -Paginate until `pageInfo.hasNextPage == false`. Batch size of 50 is safe (the open-PR selection set is lighter than `pr-triage`'s — no `statusCheckRollup`, no `reviewThreads`, no `latestReviews`). For a 300-PR backlog that's six GraphQL calls. +Paginate until `pageInfo.hasNextPage == false`. Batch size of 50 is safe (the open-PR selection set is lighter than `pr-management-triage`'s — no `statusCheckRollup`, no `reviewThreads`, no `latestReviews`). For a 300-PR backlog that's six GraphQL calls. --- @@ -152,10 +152,10 @@ The tables are Markdown (GitHub-flavoured) so the same output renders cleanly in ## What this skill does NOT do - **No mutations.** See Golden rule 1. -- **No per-PR drill-in.** The output is aggregate — if the maintainer wants to inspect a specific PR, they run `pr-triage pr:` or open it in the browser. +- **No per-PR drill-in.** The output is aggregate — if the maintainer wants to inspect a specific PR, they run `pr-management-triage pr:` or open it in the browser. - **No timeline / trend charts.** A single snapshot per invocation. Tracking week-over-week is the maintainer's job — re-run the skill at a different `since:` date if needed. - **No author-level stats.** Grouping is by area label, not by author login. A stats-by-author skill is a separate scope. -- **No PR *quality* scoring.** CI pass/fail, diff size, and review-thread counts are all omitted from the aggregate — they belong in the per-PR `pr-triage` view. +- **No PR *quality* scoring.** CI pass/fail, diff size, and review-thread counts are all omitted from the aggregate — they belong in the per-PR `pr-management-triage` view. --- diff --git a/.claude/skills/pr-stats/aggregate.md b/.claude/skills/pr-management-stats/aggregate.md similarity index 95% rename from .claude/skills/pr-stats/aggregate.md rename to .claude/skills/pr-management-stats/aggregate.md index f4b0bf7e..627e5576 100644 --- a/.claude/skills/pr-stats/aggregate.md +++ b/.claude/skills/pr-management-stats/aggregate.md @@ -22,7 +22,7 @@ Order the areas for display by total-count descending, with `(no area)` always l ## Counters (per area) -One `_AreaStats` block per area. Only two counters (`total` and `contributors`) cover all PRs; every other counter is **contributor-only** (excludes `OWNER` / `MEMBER` / `COLLABORATOR` authors). The rationale is that collaborator PRs have a different lifecycle — they're not triaged by the pr-triage skill, they don't need "ready for maintainer review" to surface, and their drafts are the author's to manage. Mixing them into the draft / triaged / responded counts dilutes every percentage on the row. +One `_AreaStats` block per area. Only two counters (`total` and `contributors`) cover all PRs; every other counter is **contributor-only** (excludes `OWNER` / `MEMBER` / `COLLABORATOR` authors). The rationale is that collaborator PRs have a different lifecycle — they're not triaged by the pr-management-triage skill, they don't need "ready for maintainer review" to surface, and their drafts are the author's to manage. Mixing them into the draft / triaged / responded counts dilutes every percentage on the row. | Field | Count rule | Scope | |---|---|---| diff --git a/.claude/skills/pr-stats/classify.md b/.claude/skills/pr-management-stats/classify.md similarity index 90% rename from .claude/skills/pr-stats/classify.md rename to .claude/skills/pr-management-stats/classify.md index ce9c93af..71c01ef3 100644 --- a/.claude/skills/pr-stats/classify.md +++ b/.claude/skills/pr-management-stats/classify.md @@ -3,7 +3,7 @@ # Classify -Per-PR state determination for the stats tables. Mirrors the triage-detection logic in the triage-marker rows in [`pr-triage/classify-and-act.md`](../pr-triage/classify-and-act.md) (rows 3–4 — `already_triaged`) — the two skills must agree on what "triaged" means. Any rule change here must ship simultaneously in `pr-triage`. +Per-PR state determination for the stats tables. Mirrors the triage-detection logic in the triage-marker rows in [`pr-management-triage/classify-and-act.md`](../pr-management-triage/classify-and-act.md) (rows 3–4 — `already_triaged`) — the two skills must agree on what "triaged" means. Any rule change here must ship simultaneously in `pr-management-triage`. Classification is pure function of state from [`fetch.md`](fetch.md) — no network calls, no writes. @@ -23,10 +23,10 @@ Two flavours of the marker circulate in `` and both must be detected: | Source | Form of marker in the comment body | Where it appears | |---|---|---| -| `pr-triage` skill / removed `breeze pr auto-triage` — violations path | `[Pull Request quality criteria](https://github.com/…)` visible link | violations-style draft / comment / close bodies | +| `pr-management-triage` skill / removed `breeze pr auto-triage` — violations path | `[Pull Request quality criteria](https://github.com/…)` visible link | violations-style draft / comment / close bodies | | Removed `breeze pr auto-triage` — staleness path (legacy comments only) | `` **HTML comment** appended to the body | staleness-close / stale-workflow / inactive-open comments posted before the command was removed | -The HTML-comment form is invisible in the GraphQL `bodyText` field (bodyText strips HTML comments). Fetching `body` preserves it, and a single substring match for `Pull Request quality criteria` catches both the visible link and the hidden HTML marker. The `pr-triage` skill currently only emits the visible-link form, but the HTML-comment form remains on PRs that were triaged before the breeze command was removed, so the detector must continue to handle both. +The HTML-comment form is invisible in the GraphQL `bodyText` field (bodyText strips HTML comments). Fetching `body` preserves it, and a single substring match for `Pull Request quality criteria` catches both the visible link and the hidden HTML marker. The `pr-management-triage` skill currently only emits the visible-link form, but the HTML-comment form remains on PRs that were triaged before the breeze command was removed, so the detector must continue to handle both. This is why [`fetch.md`](fetch.md) specifies `body` (not `bodyText`) in the comments subfield. A previous iteration of the skill used `bodyText` and missed ~10% of triaged PRs on `` — specifically, the ones that had only the staleness-style legacy auto-triage comment. diff --git a/.claude/skills/pr-stats/fetch.md b/.claude/skills/pr-management-stats/fetch.md similarity index 94% rename from .claude/skills/pr-stats/fetch.md rename to .claude/skills/pr-management-stats/fetch.md index 029bd203..b552cb5a 100644 --- a/.claude/skills/pr-stats/fetch.md +++ b/.claude/skills/pr-management-stats/fetch.md @@ -68,7 +68,7 @@ gh api graphql \ -F searchQuery="is:pr is:open repo: sort:created-asc" \ -F batchSize=50 \ -F cursor="$CURSOR" \ - --field query=@/tmp/pr-stats-open.graphql + --field query=@/tmp/pr-management-stats-open.graphql ``` ### Batch size @@ -140,7 +140,7 @@ In this case the visible body contains no "Pull Request quality criteria" text a **Always use `body`, not `bodyText`.** The marker detection is a simple substring search for `Pull Request quality criteria` against the raw body — it matches both: -- the visible `[Pull Request quality criteria](https://…)` link that the `pr-triage` skill (and the removed breeze violations-triage) emits, and +- the visible `[Pull Request quality criteria](https://…)` link that the `pr-management-triage` skill (and the removed breeze violations-triage) emits, and - the `` HTML comment that the removed breeze staleness-triage embedded as a hidden marker (still present on legacy triaged PRs). Raw bodies are slightly noisier (Markdown formatting characters) but the marker string is distinctive enough that false positives are not a concern on ``. @@ -220,7 +220,7 @@ gh api graphql \ -F searchQuery="is:pr -is:open repo: closed:>=2026-03-11 sort:updated-desc" \ -F batchSize=50 \ -F cursor="$CURSOR" \ - --field query=@/tmp/pr-stats-closed.graphql + --field query=@/tmp/pr-management-stats-closed.graphql ``` ### Cutoff default @@ -286,13 +286,13 @@ sequence (e.g. `\z`, `\e`), even `strict=False` fails with ## Why no `statusCheckRollup` / `mergeable` / `reviewThreads` -`pr-triage` needs all three for classification; `pr-stats` does not. Dropping them keeps the query complexity well below GitHub's per-page ceiling, which is how we can safely run `batchSize=50` here versus `20` in `pr-triage`. If a future stats column ever needs one of those fields, raise only that query's complexity — don't pull them into the default shape "just in case". +`pr-management-triage` needs all three for classification; `pr-management-stats` does not. Dropping them keeps the query complexity well below GitHub's per-page ceiling, which is how we can safely run `batchSize=50` here versus `20` in `pr-management-triage`. If a future stats column ever needs one of those fields, raise only that query's complexity — don't pull them into the default shape "just in case". --- ## Scratch cache -`/tmp/pr-stats-cache-.json` (where slug is `__`): +`/tmp/pr-management-stats-cache-.json` (where slug is `__`): ```json { diff --git a/.claude/skills/pr-stats/render.md b/.claude/skills/pr-management-stats/render.md similarity index 96% rename from .claude/skills/pr-stats/render.md rename to .claude/skills/pr-management-stats/render.md index 232e8b2e..5c1b9965 100644 --- a/.claude/skills/pr-stats/render.md +++ b/.claude/skills/pr-management-stats/render.md @@ -84,7 +84,7 @@ When a percentage cell is a close call (e.g. `%Responded` of exactly 50%), keep ## Triage state markers -The triage workflow categorises every non-collab PR into one of four states (the same four the now-removed `breeze pr auto-triage` overview table surfaced, and that the [`pr-triage`](../pr-triage/SKILL.md) skill continues to use): +The triage workflow categorises every non-collab PR into one of four states (the same four the now-removed `breeze pr auto-triage` overview table surfaced, and that the [`pr-management-triage`](../pr-management-triage/SKILL.md) skill continues to use): | Marker | Meaning | Colour | |---|---|---| @@ -93,7 +93,7 @@ The triage workflow categorises every non-collab PR into one of four states (the | `Responded` | author commented / pushed after the triage comment | `bright_cyan` | | `-` | not yet triaged | `blue` | -`pr-stats` surfaces the same buckets at the area level. After Table 2, print a small **state-breakdown panel** that slices the full open-PR set into the four triage-state markers: +`pr-management-stats` surfaces the same buckets at the area level. After Table 2, print a small **state-breakdown panel** that slices the full open-PR set into the four triage-state markers: ```python state_panel_lines = [ @@ -243,4 +243,4 @@ This line is plain text (no Rich markup) so it copies cleanly into Slack or a st - **No emoji in Rich output.** Colour is the visual cue. The only place emoji is allowed is the Markdown-fallback percentage cells described under *Markdown fallback*. - **No opinions.** The stats describe state; interpretation belongs to the maintainer reading them. Don't add "queue is in good shape" or "need to close stale drafts" sentences. -- **No PR-level drill-in** in the stats output. If the maintainer wants to zoom in on a specific area, the follow-up is `pr-triage label:area:`, not a stats continuation. +- **No PR-level drill-in** in the stats output. If the maintainer wants to zoom in on a specific area, the follow-up is `pr-management-triage label:area:`, not a stats continuation. diff --git a/.claude/skills/pr-triage/SKILL.md b/.claude/skills/pr-management-triage/SKILL.md similarity index 95% rename from .claude/skills/pr-triage/SKILL.md rename to .claude/skills/pr-management-triage/SKILL.md index cabe1bec..8599d55a 100644 --- a/.claude/skills/pr-triage/SKILL.md +++ b/.claude/skills/pr-management-triage/SKILL.md @@ -1,5 +1,5 @@ --- -name: pr-triage +name: pr-management-triage description: | Sweep open pull requests on the configured `` repo (default: read from `/project.md → @@ -12,7 +12,7 @@ description: | pinged to a stale reviewer, or marked `ready for maintainer review`. Does **not** perform code review (no LLM line comments, no approve/request-changes submissions) — that lives in - [`pr-maintainer-review`](../pr-maintainer-review/SKILL.md). + [`pr-management-code-review`](../pr-management-code-review/SKILL.md). when_to_use: | Invoke when a maintainer says "triage the PR queue", "go through new contributor PRs", "run the morning triage", "triage PR NNN", @@ -33,7 +33,7 @@ license: Apache-2.0 → the PR's base branch (typically `main`) Substitute these before running any `gh` command below. --> -# pr-triage +# pr-management-triage This skill walks a maintainer through **first-pass triage** of open pull requests. Its job is to answer, for each candidate PR, @@ -75,16 +75,16 @@ This skill resolves project-specific content from the adopter's `/` directory (which resolves to `.apache-steward/` in the adopter's tracker root): -- [`/pr-triage-config.md`](../../../projects/_template/pr-triage-config.md) — committers team handle, area-label prefix, project-specific labels (`ready for maintainer review`, etc.), grace windows. -- [`/pr-triage-comment-templates.md`](../../../projects/_template/pr-triage-comment-templates.md) — comment-body URLs (PR quality criteria, two-stage triage rationale), AI-attribution footer wording, project display name. -- [`/pr-triage-ci-check-map.md`](../../../projects/_template/pr-triage-ci-check-map.md) — CI-check name pattern → category name + doc-URL mapping for the violations comment. +- [`/pr-management-config.md`](../../../projects/_template/pr-management-config.md) — committers team handle, area-label prefix, project-specific labels (`ready for maintainer review`, etc.), grace windows. +- [`/pr-management-triage-comment-templates.md`](../../../projects/_template/pr-management-triage-comment-templates.md) — comment-body URLs (PR quality criteria, two-stage triage rationale), AI-attribution footer wording, project display name. +- [`/pr-management-triage-ci-check-map.md`](../../../projects/_template/pr-management-triage-ci-check-map.md) — CI-check name pattern → category name + doc-URL mapping for the violations comment. The framework currently ships with airflow-flavored defaults inline in the supporting files of this skill (comment-templates.md, classify-and-act.md, etc.). Follow-up work will move those out to the adopter config so the skill is fully project-agnostic — until then, non-airflow adopters override by forking the relevant -supporting files into their own `.claude/skills/pr-triage/`. +supporting files into their own `.claude/skills/pr-management-triage/`. --- @@ -272,7 +272,7 @@ touching any PR: missing ones degrade to "post the comment, skip the label" with a warning. 3. Initialise (or read) the session cache at - `/tmp/pr-triage-cache-.json` (see + `/tmp/pr-management-triage-cache-.json` (see [`fetch-and-batch.md#session-cache`](fetch-and-batch.md)). A failure of step 1 is a **stop** — surface it and ask the diff --git a/.claude/skills/pr-triage/actions.md b/.claude/skills/pr-management-triage/actions.md similarity index 100% rename from .claude/skills/pr-triage/actions.md rename to .claude/skills/pr-management-triage/actions.md diff --git a/.claude/skills/pr-triage/classify-and-act.md b/.claude/skills/pr-management-triage/classify-and-act.md similarity index 100% rename from .claude/skills/pr-triage/classify-and-act.md rename to .claude/skills/pr-management-triage/classify-and-act.md diff --git a/.claude/skills/pr-triage/comment-templates.md b/.claude/skills/pr-management-triage/comment-templates.md similarity index 100% rename from .claude/skills/pr-triage/comment-templates.md rename to .claude/skills/pr-management-triage/comment-templates.md diff --git a/.claude/skills/pr-triage/fetch-and-batch.md b/.claude/skills/pr-management-triage/fetch-and-batch.md similarity index 99% rename from .claude/skills/pr-triage/fetch-and-batch.md rename to .claude/skills/pr-management-triage/fetch-and-batch.md index 64612cb3..13a74e41 100644 --- a/.claude/skills/pr-triage/fetch-and-batch.md +++ b/.claude/skills/pr-management-triage/fetch-and-batch.md @@ -334,7 +334,7 @@ don't prefetch. ## Session cache -`/tmp/pr-triage-cache-.json` stores intermediate +`/tmp/pr-management-triage-cache-.json` stores intermediate results so that re-invocations inside a working session skip anything that isn't needed. Schema: diff --git a/.claude/skills/pr-triage/interaction-loop.md b/.claude/skills/pr-management-triage/interaction-loop.md similarity index 100% rename from .claude/skills/pr-triage/interaction-loop.md rename to .claude/skills/pr-management-triage/interaction-loop.md diff --git a/.claude/skills/pr-triage/prerequisites.md b/.claude/skills/pr-management-triage/prerequisites.md similarity index 98% rename from .claude/skills/pr-triage/prerequisites.md rename to .claude/skills/pr-management-triage/prerequisites.md index 6668d28a..3cf3edbc 100644 --- a/.claude/skills/pr-triage/prerequisites.md +++ b/.claude/skills/pr-management-triage/prerequisites.md @@ -112,7 +112,7 @@ a missing label is itself an anomaly worth flagging. ## 4. Session scratch cache available (non-blocking) The scratch cache lives at -`/tmp/pr-triage-cache-.json` where `` is +`/tmp/pr-management-triage-cache-.json` where `` is `__` (e.g. `apache__airflow`). It stores: - viewer login and `viewerPermission` (so we don't re-check in diff --git a/.claude/skills/pr-triage/rationale.md b/.claude/skills/pr-management-triage/rationale.md similarity index 100% rename from .claude/skills/pr-triage/rationale.md rename to .claude/skills/pr-management-triage/rationale.md diff --git a/.claude/skills/pr-triage/stale-sweeps.md b/.claude/skills/pr-management-triage/stale-sweeps.md similarity index 100% rename from .claude/skills/pr-triage/stale-sweeps.md rename to .claude/skills/pr-management-triage/stale-sweeps.md diff --git a/.claude/skills/pr-triage/workflow-approval.md b/.claude/skills/pr-management-triage/workflow-approval.md similarity index 100% rename from .claude/skills/pr-triage/workflow-approval.md rename to .claude/skills/pr-management-triage/workflow-approval.md diff --git a/.claude/skills/security-allocate-cve/SKILL.md b/.claude/skills/security-cve-allocate/SKILL.md similarity index 96% rename from .claude/skills/security-allocate-cve/SKILL.md rename to .claude/skills/security-cve-allocate/SKILL.md index 0e5eb8c5..5fc31b3c 100644 --- a/.claude/skills/security-allocate-cve/SKILL.md +++ b/.claude/skills/security-cve-allocate/SKILL.md @@ -1,5 +1,5 @@ --- -name: security-allocate-cve +name: security-cve-allocate description: | Walk a security team member through allocating a CVE for an tracking issue. Prints the ASF Vulnogram @@ -11,7 +11,7 @@ description: | *CVE tool link* field, adds the `cve allocated` label, posts a collapsed status-change comment, and runs `generate-cve-json --attach` to embed the paste-ready JSON in the body. Finishes by - handing off to the `security-sync-issues` skill to reconcile the + handing off to the `security-issue-sync` skill to reconcile the rest of the tracker (milestone, assignee, reporter drafts, fix-PR state) now that the CVE landing is complete. when_to_use: | @@ -32,7 +32,7 @@ when_to_use: | Before running any bash command below, substitute these with the concrete values from the adopting project's /project.md. --> -# security-allocate-cve +# security-cve-allocate Walks a security team member through the CVE-allocation step of the [handling process](../../../README.md) for a given @@ -81,7 +81,7 @@ of the allocated ID does not need to be done by the PMC member. **Golden rule — every `` reference is a clickable link**, per Golden rule 2 in -[`security-sync-issues`](../security-sync-issues/SKILL.md). The +[`security-issue-sync`](../security-issue-sync/SKILL.md). The allocation recipe, the post-allocation proposal, and the status- change comment must all follow the link-form convention from [`AGENTS.md`](../../../AGENTS.md). @@ -345,7 +345,7 @@ user to confirm. Numbered items: 1. **Set the *CVE tool link* body field** to `https://cveprocess.apache.org/cve5/CVE-YYYY-NNNNN`. Patch only this one field; do not touch the rest of the body. Use the - `security-sync-issues` skill's body-field-surgery recipe — read + `security-issue-sync` skill's body-field-surgery recipe — read the full body, replace the *CVE tool link* field's value between its `### CVE tool link\n\n` header and the next `### ` or end-of-body, write back via `gh issue edit --body-file`. @@ -363,8 +363,8 @@ user to confirm. Numbered items: creates one; on the way, the skill must also fold any pre-existing legacy bot comments into the new rollup per the fold-legacy sub-step described in - [`security-sync-issues`](../security-sync-issues/SKILL.md) — - security-allocate-cve is a common first write after a long pause, so + [`security-issue-sync`](../security-issue-sync/SKILL.md) — + security-cve-allocate is a common first write after a long pause, so the legacy comments are often there. 4. **Regenerate the CVE JSON attachment** in the tracker body by running @@ -374,12 +374,12 @@ user to confirm. Numbered items: This is how the CVE record first gets seeded with the allocated ID. The remediation-developer credit (if any) comes from the tracker's *Remediation developer* body field — populated by the - `security-sync-issues` skill from the linked PR's author the + `security-issue-sync` skill from the linked PR's author the first time *PR with the fix* is set, and editable by hand thereafter. No CLI flag needed. 5. **Draft a reporter status update** — only when the real reporter's Gmail thread is known and the ball is in our court - (see `security-sync-issues` Step 1c). Keep the draft short, per + (see `security-issue-sync` Step 1c). Keep the draft short, per the "Brevity: emails state facts, not context" section of [`AGENTS.md`](../../../AGENTS.md): one sentence that the CVE has been allocated, one sentence that the advisory will be sent @@ -434,7 +434,7 @@ spaces inside the block, one blank line after - Label `cve allocated` added. - CVE JSON attachment embedded in the issue body — paste into [Vulnogram `#source`](https://cveprocess.apache.org/cve5/#source) to seed the record. -**Next:** . +**Next:** . @@ -496,16 +496,16 @@ partial failures stay legible: If any step fails, stop and ask the user how to proceed — do not guess. The body edit (step 1) is the only *load-bearing* step; if -steps 2–5 fail, a subsequent `security-sync-issues` run will pick up +steps 2–5 fail, a subsequent `security-issue-sync` run will pick up the slack because it reads the CVE ID from the body. --- -## Step 6 — Hand off to `security-sync-issues` +## Step 6 — Hand off to `security-issue-sync` Right after the apply loop finishes (and before the recap in Step 7), invoke the -[`security-sync-issues`](../security-sync-issues/SKILL.md) skill on +[`security-issue-sync`](../security-issue-sync/SKILL.md) skill on the same tracker. The CVE allocation touches every axis the sync skill reconciles — labels, body fields, assignees, milestone, reporter-notification drafts, cross-referenced fix PRs — and @@ -526,7 +526,7 @@ that the next triage sweep has to clean up from scratch. Always run it. **How to invoke.** The sync skill is prompt-driven, so this is a -meta-step: tell the user *"running `security-sync-issues` on +meta-step: tell the user *"running `security-issue-sync` on [#](...) to reconcile the rest of the tracker"* and then run the sync skill's Step 1 (Gather state) on the same issue. Sync produces its own numbered proposal with its @@ -542,7 +542,7 @@ bump. **When the handoff is not appropriate.** Skip the sync handoff **only** if the user explicitly says they are about to close the tracker (e.g. allocated-then-decided-to-reject — a rare case, but -possible), or if sync was already running when `security-allocate-cve` was +possible), or if sync was already running when `security-cve-allocate` was invoked (nested invocation — sync's own Step 1 will detect the fresh CVE on its next pass anyway). In every other case, run it. @@ -607,7 +607,7 @@ presenting. particular step 6 (CVE allocation). - [`AGENTS.md`](../../../AGENTS.md) — confidentiality, linking conventions, reporter-supplied CVSS rule. -- [`security-sync-issues`](../security-sync-issues/SKILL.md) — +- [`security-issue-sync`](../security-issue-sync/SKILL.md) — **mandatory follow-up** to this skill (Step 6). Reconciles the tracker, the mail thread, and any fix PR after the CVE landing touches labels, body fields, and comments. Always runs; only @@ -615,11 +615,11 @@ presenting. - [`generate-cve-json`](../../../tools/vulnogram/generate-cve-json/SKILL.md) — Step 4 regenerates the CVE JSON attachment in the body so Vulnogram can be seeded via the `#source` tab paste. -- [`security-import-issues`](../security-import-issues/SKILL.md) / - [`security-deduplicate-issues`](../security-deduplicate-issues/SKILL.md) +- [`security-issue-import`](../security-issue-import/SKILL.md) / + [`security-issue-deduplicate`](../security-issue-deduplicate/SKILL.md) — the two on-ramps that feed trackers into this skill; running dedupe before allocation is how we avoid burning two CVE IDs on the same root-cause bug. -- [`security-fix-issue`](../security-fix-issue/SKILL.md) — the +- [`security-issue-fix`](../security-issue-fix/SKILL.md) — the follow-up after allocation: open the public fix PR with the CVE context kept internal. diff --git a/.claude/skills/security-deduplicate-issues/SKILL.md b/.claude/skills/security-issue-deduplicate/SKILL.md similarity index 96% rename from .claude/skills/security-deduplicate-issues/SKILL.md rename to .claude/skills/security-issue-deduplicate/SKILL.md index 2dc96e67..5d88b622 100644 --- a/.claude/skills/security-deduplicate-issues/SKILL.md +++ b/.claude/skills/security-issue-deduplicate/SKILL.md @@ -1,5 +1,5 @@ --- -name: security-deduplicate-issues +name: security-issue-deduplicate description: | Merge two tracking issues that describe the same root-cause vulnerability (typically discovered independently by two @@ -12,7 +12,7 @@ description: | when_to_use: | Invoke when a security team member says "dedupe #NNN and #MMM", "merge #MMM into #NNN", "#MMM is a duplicate of #NNN", or when the - security-import-issues skill's Step 2a surfaces a STRONG match (GHSA + security-issue-import skill's Step 2a surfaces a STRONG match (GHSA ID collision) between a new report and an existing tracker. Also appropriate as a periodic cleanup action when a triager spots two open trackers describing the same bug from different angles. @@ -27,7 +27,7 @@ when_to_use: | Before running any bash command below, substitute these with the concrete values from the adopting project's /project.md. --> -# security-deduplicate-issues +# security-issue-deduplicate Merges two `` tracking issues that describe the same underlying vulnerability. The output is a single tracker @@ -55,7 +55,7 @@ different **scope labels** (`airflow` vs. `providers`, `airflow` vs. `chart`, etc.) must not be merged. If an external reporter rediscovers the same bug in two different products' surfaces, that is a multi-scope report and the resolution is a -**scope split** handled by the `security-sync-issues` skill, not a +**scope split** handled by the `security-issue-sync` skill, not a dedupe. This skill refuses to operate when the two candidate trackers have different scope labels, and the proposal says so explicitly. @@ -129,7 +129,7 @@ Verify: - Both have the **same scope label** — `airflow` vs. `airflow`, or `providers` vs. `providers`, or `chart` vs. `chart`. If the scope labels differ, refuse the merge and tell the user this is - a multi-scope report to be handled by `security-sync-issues`'s + a multi-scope report to be handled by `security-issue-sync`'s scope-split flow instead. - Neither tracker is already labelled `duplicate` (that would indicate a partial-merge already happened and someone left it @@ -286,7 +286,7 @@ merges. Two rollup-comment entries, one per tracker — **not** two new top-level comments. The entries are appended to each tracker's -existing status-rollup comment (created by `security-import-issues`) +existing status-rollup comment (created by `security-issue-import`) via the upsert recipe in [`tools/github/status-rollup.md`](../../../tools/github/status-rollup.md#upsert-recipe--append-to-an-existing-rollup-or-create-one). When either tracker does not yet carry a rollup (legacy tracker @@ -387,7 +387,7 @@ After confirmation, apply **sequentially** (never in parallel): the rollup if none exists yet. The same step folds any legacy bot comments on the kept tracker into the rollup first, per the fold-legacy sub-step in - [`security-sync-issues`](../security-sync-issues/SKILL.md). + [`security-issue-sync`](../security-issue-sync/SKILL.md). 3. Rollup-comment upsert on the dropped tracker — append the `Merge (dropped)` entry (same recipe; fold legacy comments first when needed). @@ -399,7 +399,7 @@ After confirmation, apply **sequentially** (never in parallel): 6. `uv run --project /tools/vulnogram/generate-cve-json generate-cve-json --attach` — the *Remediation developer* body field is the source of truth for remediation-developer credits (populated by the - `security-sync-issues` skill from the linked PR's author); no CLI + `security-issue-sync` skill from the linked PR's author); no CLI flag needed 7. For each legacy bot comment folded in steps 2 / 3, delete the original with `gh api -X DELETE @@ -434,7 +434,7 @@ recap before presenting. ## Hard rules - **Never merge across scopes.** Different scope labels → scope - split (via `security-sync-issues`), not dedupe. + split (via `security-issue-sync`), not dedupe. - **Never re-synthesize credits.** Copy each reporter's credit line verbatim from their tracker. - **Never propagate a reporter-supplied CVSS** from the dropped @@ -457,7 +457,7 @@ recap before presenting. ## When dedupe is **not** appropriate - The two trackers are in **different scopes** → use the scope-split - flow in `security-sync-issues` instead. + flow in `security-issue-sync` instead. - The two trackers describe the same code surface but **different bugs** with **different fixes** (for example, two separate allowlist gaps in the same file, each requiring its own @@ -476,11 +476,11 @@ recap before presenting. - [`README.md`](../../../README.md) — the handling process; duplicates are resolved here at various steps rather than at a single numbered step. -- [`security-import-issues`](../security-import-issues/SKILL.md) — +- [`security-issue-import`](../security-issue-import/SKILL.md) — Step 2a surfaces potential duplicates before a new tracker is even created, so in the ideal case this skill is never needed on a fresh import. -- [`security-sync-issues`](../security-sync-issues/SKILL.md) — runs +- [`security-issue-sync`](../security-issue-sync/SKILL.md) — runs on the kept tracker after the merge to reconcile labels / milestone / credit-preference drafts for both reporters. - [`generate-cve-json`](../../../tools/vulnogram/generate-cve-json/SKILL.md) — diff --git a/.claude/skills/security-fix-issue/SKILL.md b/.claude/skills/security-issue-fix/SKILL.md similarity index 97% rename from .claude/skills/security-fix-issue/SKILL.md rename to .claude/skills/security-issue-fix/SKILL.md index 41fa5055..7695cb90 100644 --- a/.claude/skills/security-fix-issue/SKILL.md +++ b/.claude/skills/security-issue-fix/SKILL.md @@ -1,9 +1,9 @@ --- -name: security-fix-issue +name: security-issue-fix description: | Attempt to fix a security issue tracked in by implementing the change in a public PR. Runs the - security-sync-issues skill first to reconcile the issue's state, then + security-issue-sync skill first to reconcile the issue's state, then analyses the discussion to decide whether the issue is easily fixable (clear consensus, small scope, known location). If it is, proposes an implementation plan, waits for explicit user confirmation, writes the @@ -33,11 +33,11 @@ when_to_use: | Before running any bash command below, substitute these with the concrete values from the adopting project's /project.md. --> -# security-fix-issue +# security-issue-fix This skill automates the "attempt a fix" step of the security handling process for issues in [``](https://github.com/). -It composes with the [`security-sync-issues`](../security-sync-issues/SKILL.md) +It composes with the [`security-issue-sync`](../security-issue-sync/SKILL.md) skill — it always runs the sync first so that the issue's state is reconciled with the mail thread and any existing PRs before attempting any new work. @@ -167,7 +167,7 @@ Only after **every** check is green, proceed to Step 1. ## Step 1 — Sync the issue first -Run the [`security-sync-issues`](../security-sync-issues/SKILL.md) skill +Run the [`security-issue-sync`](../security-issue-sync/SKILL.md) skill on the same issue number and apply any state corrections the user confirms there. **Do not attempt a fix before the sync has completed**, because: @@ -552,7 +552,7 @@ Now that a public PR exists, update the private tracking issue: convention), run the upsert recipe's Step 2b to create it and fold any pre-existing bot comments into the new rollup first — see the fold-legacy sub-step in - [`security-sync-issues`](../security-sync-issues/SKILL.md). + [`security-issue-sync`](../security-issue-sync/SKILL.md). Before writing the entry, **scrub the body for bare-name mentions** of project maintainers, release managers, and @@ -570,14 +570,14 @@ Now that a public PR exists, update the private tracking issue: 2. **Update the issue body "PR with the fix" field** if it is empty or points to a stale PR. Use `gh issue view --json body`, patch only that field, and apply via `gh issue edit --body-file`, as - in the [`security-sync-issues`](../security-sync-issues/SKILL.md) + in the [`security-issue-sync`](../security-issue-sync/SKILL.md) skill. 3. **Maintain milestones and labels** — see the next section. 4. **Status update to the reporter** — if the issue has an identified external reporter and the reporter has not yet been - told about the fix PR, delegate to the `security-sync-issues` + told about the fix PR, delegate to the `security-issue-sync` skill's "Status update to the reporter" category by re-running that skill with a pointer to the new PR. Do **not** draft the reporter email directly in this skill — it is the sync skill's @@ -661,7 +661,7 @@ For a post-triage, pre-merge fix, the target label set is: - `needs triage` **removed** (if still present after triage); - `pr created` once the public PR is open; - **not** `pr merged` or `fix released` (those belong to post-merge - / post-release states, applied by the `security-sync-issues` skill + / post-release states, applied by the `security-issue-sync` skill on later runs); - **not** `announced - emails sent` or `announced` (those belong to post-advisory states, also applied by the sync skill). @@ -723,7 +723,7 @@ Print a short recap: - the comment posted on the `` issue, - the backport label that was applied (or a note that none was needed), - the next step — typically *"wait for review; re-run - security-sync-issues after the PR merges to transition the issue + security-issue-sync after the PR merges to transition the issue from `pr created` to `pr merged` and update the milestone"*. --- @@ -766,7 +766,7 @@ Print a short recap: ## References -- [`security-sync-issues` skill](../security-sync-issues/SKILL.md) — run this first. +- [`security-issue-sync` skill](../security-issue-sync/SKILL.md) — run this first. - [`README.md`](../../../README.md) — canonical process description, especially steps 7–9 (implementing the fix). - [`AGENTS.md`](../../../AGENTS.md) — repo-wide rules (confidentiality, commit trailers, tone, CVE linking). - [`/AGENTS.md`](https://github.com//blob/main/AGENTS.md) — parent conventions this skill defers to. diff --git a/.claude/skills/security-import-issues-from-md/SKILL.md b/.claude/skills/security-issue-import-from-md/SKILL.md similarity index 96% rename from .claude/skills/security-import-issues-from-md/SKILL.md rename to .claude/skills/security-issue-import-from-md/SKILL.md index 352aa8fc..4e9368e8 100644 --- a/.claude/skills/security-import-issues-from-md/SKILL.md +++ b/.claude/skills/security-issue-import-from-md/SKILL.md @@ -1,13 +1,13 @@ --- -name: security-import-issues-from-md +name: security-issue-import-from-md description: | Open one or more `` tracking issues from a markdown file containing a batch of security findings (typically the output of an AI security review or a third-party scanner). Each finding in the file becomes one tracker, landing in the `Needs triage` board column with the standard issue-template body fields populated from - the markdown sections. Unlike `security-import-issues` (Gmail) and - `security-import-issue-from-pr` (public PR), there is no inbound + the markdown sections. Unlike `security-issue-import` (Gmail) and + `security-issue-import-from-pr` (public PR), there is no inbound reporter to reply to and no PR to inspect — the file itself is the full report. when_to_use: | @@ -19,8 +19,8 @@ when_to_use: | third-party SAST report exported as markdown, or a security consultant's findings document. Not appropriate when a single inbound report is best handled through the Gmail path - (`security-import-issues`) or when there is a public PR to anchor - the import on (`security-import-issue-from-pr`). + (`security-issue-import`) or when there is a public PR to anchor + the import on (`security-issue-import-from-pr`). --- -# security-import-issues-from-md +# security-issue-import-from-md This skill is the **batch on-ramp** of the security-issue handling process for the case where the security team has a markdown file @@ -47,7 +47,7 @@ can run. It is the third on-ramp variant alongside the two existing import skills: -| | `security-import-issues` | `security-import-issue-from-pr` | `security-import-issues-from-md` | +| | `security-issue-import` | `security-issue-import-from-pr` | `security-issue-import-from-md` | |---|---|---|---| | Source | `` Gmail / PonyMail thread | `` PR URL or number | Markdown file with one or more findings | | Reporter | External researcher | None (PR author = remediation developer) | None (the file is the report; usually AI- or scanner-generated) | @@ -79,7 +79,7 @@ surface the URL points at. **Golden rule — propose every finding individually before applying.** Even when the input is a 50-finding file, the skill surfaces a proposal table listing every finding and waits for explicit -confirmation. The default disposition mirrors `security-import-issues`: +confirmation. The default disposition mirrors `security-issue-import`: *import all unless rejected upfront* (`skip N` to drop a specific candidate). A bare `go` / `proceed` / `yes, all` imports every non-rejected candidate. The skill must still render each candidate @@ -249,7 +249,7 @@ convention; see ``` The title is left otherwise untouched — this skill does not run the -title-normalisation cascade (that lives in `security-allocate-cve`, by which +title-normalisation cascade (that lives in `security-cve-allocate`, by which point the validity of the report is established). ### 3b — Issue body @@ -384,7 +384,7 @@ GitHub rate limits cleanly when serialised. Bypasses the form so the `Security mailing list thread` required-field check does not fire. Same pattern as -[`security-import-issue-from-pr`'s](../security-import-issue-from-pr/SKILL.md#7a--create-the-tracker-via-gh-api) Step 7a. +[`security-issue-import-from-pr`'s](../security-issue-import-from-pr/SKILL.md#7a--create-the-tracker-via-gh-api) Step 7a. Write the body to a temp file (per finding): @@ -565,10 +565,10 @@ Print a one-screen recap: Then a one-line hand-off: > Next: triage each new tracker per Step 3 of the handling -> process. Run [`security-sync-issues`](../security-sync-issues/SKILL.md) +> process. Run [`security-issue-sync`](../security-issue-sync/SKILL.md) > on `#NNN` once the validity discussion progresses. -Do **not** auto-invoke `security-sync-issues` — these trackers are +Do **not** auto-invoke `security-issue-sync` — these trackers are freshly created in `Needs triage` and have nothing to sync until the validity discussion produces signal. @@ -586,7 +586,7 @@ the validity discussion produces signal. - **Does not allocate CVEs.** A finding tagged `**Severity:** HIGH` in the source markdown is *still* unassessed from the security team's perspective; the CVE-allocation gate (per - [`security-allocate-cve`](../security-allocate-cve/SKILL.md)) requires the team's + [`security-cve-allocate`](../security-cve-allocate/SKILL.md)) requires the team's own validity decision first. - **Does not parse markdown formats other than the one documented in Step 1.** If the input file uses a different shape (e.g. diff --git a/.claude/skills/security-import-issue-from-pr/SKILL.md b/.claude/skills/security-issue-import-from-pr/SKILL.md similarity index 94% rename from .claude/skills/security-import-issue-from-pr/SKILL.md rename to .claude/skills/security-issue-import-from-pr/SKILL.md index 79f6a8c7..4d718345 100644 --- a/.claude/skills/security-import-issue-from-pr/SKILL.md +++ b/.claude/skills/security-issue-import-from-pr/SKILL.md @@ -1,5 +1,5 @@ --- -name: security-import-issue-from-pr +name: security-issue-import-from-pr description: | Open a tracking issue in for a security-relevant fix that has already been opened (or merged) as a public PR in , @@ -9,7 +9,7 @@ description: | happened) with the scope label applied, `pr created` / `pr merged` reflecting the PR's state, and `Remediation developer` / `PR with the fix` body fields populated from the PR — ready for - `security-allocate-cve` to take over. + `security-cve-allocate` to take over. when_to_use: | Invoke when a security team member says "import a tracker from PR ", "open a tracker for #NNN", "we need a CVE @@ -18,7 +18,7 @@ when_to_use: | that never went through `security@`. Use only when the PR's security relevance has already been agreed informally; this skill does not host a validity discussion. For reports that arrive on - ``, use `security-import-issues`. + ``, use `security-issue-import`. --- -# security-import-issue-from-pr +# security-issue-import-from-pr This skill is an alternative on-ramp of the security-issue handling process for the case where the report **never arrived on @@ -39,12 +39,12 @@ in ``; somebody on the security team noticed it is security-relevant; the team decided informally that the fix warrants a CVE. This skill turns that public PR into an `` tracking issue so the rest of the workflow -(`security-allocate-cve` → `security-sync-issues` → `security-fix-issue` → +(`security-cve-allocate` → `security-issue-sync` → `security-issue-fix` → public advisory) can run. -It is the smaller sibling of [`security-import-issues`](../security-import-issues/SKILL.md): +It is the smaller sibling of [`security-issue-import`](../security-issue-import/SKILL.md): -| | `security-import-issues` | `security-import-issue-from-pr` | +| | `security-issue-import` | `security-issue-import-from-pr` | |---|---|---| | Source | `` Gmail / PonyMail thread | `` PR URL or number | | Reporter present | Yes (external researcher) | No (PR author = remediation developer = de-facto finder) | @@ -76,7 +76,7 @@ tracker URL itself is a public-safe identifier per the rule and may appear in the public PR description as a cross-reference, **so long as the surrounding text does not frame the change as a security fix**. The -[`security-fix-issue`](../security-fix-issue/SKILL.md) public-PR +[`security-issue-fix`](../security-issue-fix/SKILL.md) public-PR guardrails apply in full from the moment the tracker exists: neutral bug-fix language, no `CVE-`, no *"vulnerability"* or *"security fix"* phrasing. @@ -234,7 +234,7 @@ is a manual project-board action, not part of this skill. Before proposing a new tracker, check that one does not already exist for this PR. The PR URL and number are both reliable discriminators because the *PR with the fix* body field on -existing trackers contains the URL once `security-sync-issues` +existing trackers contains the URL once `security-issue-sync` has run on them. ```bash @@ -255,7 +255,7 @@ If either search returns a hit: - Surface the existing tracker(s) to the user with a clickable `#NNN` reference. - **Stop** — do not create a duplicate tracker. The user either - re-invokes `security-sync-issues NNN` to refresh the existing + re-invokes `security-issue-sync NNN` to refresh the existing tracker's PR-state labels, or (if the existing tracker is closed and the fix needs re-tracking) invokes the skill again with an explicit `force` argument. @@ -279,7 +279,7 @@ Start from `pr.title`. Strip: Do **not** add `: :` (e.g. `Apache Airflow:`) prefix — that lives in the CVE title, not the tracker title (the -[`security-allocate-cve`](../security-allocate-cve/SKILL.md) skill normalises for +[`security-cve-allocate`](../security-cve-allocate/SKILL.md) skill normalises for the CVE record). Tracker titles in `` are plain-language summaries. @@ -299,14 +299,14 @@ has nine fields. Fill them as follows: | **The issue description** | Two paragraphs: (1) a one-line note `> **Imported from public PR #** — there is no inbound \`security@\` report; the PR description below is the public statement of the vulnerability.` (2) the PR body verbatim, fenced if it is heavily templated. | | **Short public summary for publish** | `_No response_` (the team writes this when drafting the advisory; not derivable from the PR). | | **Affected versions** | Per the scope's *Affected versions* convention from [`scope-labels.md`](../../..//scope-labels.md). For `providers`: one line per affected package, ` < NEXT VERSION`. For `airflow` / `chart`: `< X.Y.Z` from the milestone. | -| **Security mailing list thread** | Sentinel: `N/A — opened from public PR #; no security@ thread`. The field is `required: true` in the form — the skill creates the issue via `gh api` (Step 7), which bypasses form-required-field enforcement, but the sentinel is still set so future `security-sync-issues` runs do not flag the field as missing. | +| **Security mailing list thread** | Sentinel: `N/A — opened from public PR #; no security@ thread`. The field is `required: true` in the form — the skill creates the issue via `gh api` (Step 7), which bypasses form-required-field enforcement, but the sentinel is still set so future `security-issue-sync` runs do not flag the field as missing. | | **Public advisory URL** | `_No response_`. | | **Reporter credited as** | `_No response_`. **The PR author is *not* credited as the CVE reporter for this kind of import.** A public PR is not a responsible disclosure — the contributor went straight to the public fix without giving the security team a chance to coordinate the announcement, so the security team neither owes a finder credit nor wants to incentivise the practice. The user can populate the field manually if there is a project-specific reason to credit a different individual (e.g. an internal reviewer who privately flagged the issue on the PR before it landed). See *[Reporter credit policy for public-PR imports](#reporter-credit-policy-for-public-pr-imports)* below. | | **PR with the fix** | `pr.url` (e.g. `https://github.com//pull/65703`). | | **Remediation developer** | `pr.author.name` (fall back to `pr.author.login`). One name per line. | | **CWE** | `_No response_` (the team assesses; not derivable). | | **Severity** | `Unknown`. | -| **CVE tool link** | `_No response_` (filled by [`security-allocate-cve`](../security-allocate-cve/SKILL.md)). | +| **CVE tool link** | `_No response_` (filled by [`security-cve-allocate`](../security-cve-allocate/SKILL.md)). | The body is written to a temp file in Step 7; in the proposal, show it inline so the user can scan-and-redirect before any @@ -386,12 +386,12 @@ The first entry on the tracker's status rollup. Shape per This tracker was deliberately opened by the security team for a public fix that did **not** arrive on ``. The validity assessment was made informally before invocation; the tracker landed in the `Assessed` column accordingly. -**Next:** Step 6 — allocate the CVE via the [`security-allocate-cve`](https://github.com//blob//.claude/skills/security-allocate-cve/SKILL.md) skill. +**Next:** Step 6 — allocate the CVE via the [`security-cve-allocate`](https://github.com//blob//.claude/skills/security-cve-allocate/SKILL.md) skill. Provenance: public PR , author `@`. Extracted fields: scope=``, *PR with the fix*=, *Remediation developer*=, *Affected versions*=``, Severity=`Unknown`. -*Reporter credited as* intentionally left blank — public-PR imports do not credit the PR author as the CVE reporter (no responsible disclosure). See the [Reporter credit policy](https://github.com//blob//.claude/skills/security-import-issue-from-pr/SKILL.md#reporter-credit-policy-for-public-pr-imports) section of the skill for the rationale. +*Reporter credited as* intentionally left blank — public-PR imports do not credit the PR author as the CVE reporter (no responsible disclosure). See the [Reporter credit policy](https://github.com//blob//.claude/skills/security-issue-import-from-pr/SKILL.md#reporter-credit-policy-for-public-pr-imports) section of the skill for the rationale. ``` Zero-whitespace rules from @@ -430,7 +430,7 @@ Confirmation forms: `reporter: Anonymous, severity: Important`. - `cancel` / `none` / `hold off` — bail; no tracker created. -Do **not** auto-default to import the way `security-import-issues` +Do **not** auto-default to import the way `security-issue-import` does. This skill is invoked deliberately on a single PR; spending one round-trip on explicit confirmation is the right trade. The proposal-to-confirmation pause also lets the user @@ -447,7 +447,7 @@ Sequenced. Each step depends on the previous one's output. Bypasses the form so the `Security mailing list thread` required-field check does not fire. Equivalent to -[`security-import-issues`'s](../security-import-issues/SKILL.md) Step 7. +[`security-issue-import`'s](../security-issue-import/SKILL.md) Step 7. Write the body to a temp file: @@ -612,9 +612,9 @@ Print a one-screen recap: Then a one-line hand-off: > Next: allocate the CVE for this tracker. Run -> [`security-allocate-cve`](../security-allocate-cve/SKILL.md) on `#NNN`. +> [`security-cve-allocate`](../security-cve-allocate/SKILL.md) on `#NNN`. -Do **not** auto-invoke `security-allocate-cve` — CVE allocation is +Do **not** auto-invoke `security-cve-allocate` — CVE allocation is PMC-gated (a non-PMC triager must relay the allocation request to a PMC member), and the user may want to batch the allocation with other trackers. @@ -642,7 +642,7 @@ with other trackers. verbatim quote from the tracker discussion. See the [Confidentiality of ``](../../../AGENTS.md#confidentiality-of-the-tracker-repository) rule. -- **Does not run `security-sync-issues` on the new tracker.** The +- **Does not run `security-issue-sync` on the new tracker.** The initial body is already coherent; sync's job (reconciling PR state, milestone, assignee against current reality) is not needed on a tracker that is being created from those exact @@ -696,7 +696,7 @@ PR state `OPEN`, milestone `Airflow 3.2.3`. Files all under Milestone: `Airflow 3.2.3`. Labels: `airflow`, `pr created`, `security issue`. *Affected versions*: `< 3.2.3`. The skill proposes everything; on user confirmation, the tracker lands -`Assessed`, ready for `security-allocate-cve`. +`Assessed`, ready for `security-cve-allocate`. ### Example 3 — Mixed-scope PR (blocker) diff --git a/.claude/skills/security-import-issues/SKILL.md b/.claude/skills/security-issue-import/SKILL.md similarity index 97% rename from .claude/skills/security-import-issues/SKILL.md rename to .claude/skills/security-issue-import/SKILL.md index 3e7985b0..7fb023c8 100644 --- a/.claude/skills/security-import-issues/SKILL.md +++ b/.claude/skills/security-issue-import/SKILL.md @@ -1,5 +1,5 @@ --- -name: security-import-issues +name: security-issue-import description: | Scan for reports that have not yet been copied into as tracking issues, present the proposed @@ -8,8 +8,8 @@ description: | `Needs triage` project-board status and draft a receipt-of- confirmation reply to each reporter. This is the first step of the handling process: the entry point that converts an inbound email - thread into a tracker the rest of the skills (security-sync-issues, - security-fix-issue, generate-cve-json) operate on. + thread into a tracker the rest of the skills (security-issue-sync, + security-issue-fix, generate-cve-json) operate on. when_to_use: | Invoke when a security team member says "import new reports", "check for unimported security@ messages", "import #", or when @@ -30,7 +30,7 @@ when_to_use: | Before running any bash command below, substitute these with the concrete values from the adopting project's /project.md. --> -# security-import-issues +# security-issue-import This skill is the **on-ramp** of the security-issue handling process. It converts an inbound `` email thread into @@ -189,7 +189,7 @@ tooling / GitHub-notification / mailing-list chatter that isn't a report: Use the canonical candidate-listing query template from -[`tools/gmail/search-queries.md`](../../../tools/gmail/search-queries.md#security-import-issues--candidate-listing-query); +[`tools/gmail/search-queries.md`](../../../tools/gmail/search-queries.md#security-issue-import--candidate-listing-query); substitute the adopting project's `` (Airflow: ``) and the project's GitHub-notification exclusions — both declared in @@ -448,7 +448,7 @@ duplicates* sub-item in the Step 5 proposal — format: When at least one **STRONG** match is found (GHSA ID collision), do **not** propose creating a new tracker. Instead, propose invoking -the [`security-deduplicate-issues`](../security-deduplicate-issues/SKILL.md) +the [`security-issue-deduplicate`](../security-issue-deduplicate/SKILL.md) skill to merge the new report's body, reporter credit, and mailing-list-thread entries into the existing tracker, and to close the new thread's would-be tracker with a `duplicate` label. @@ -503,7 +503,7 @@ image-scan dump). Skip Step 2b on candidates Step 2a flagged STRONG **Search recipe — two Gmail calls per candidate, maximum.** The query templates and the substitution-values guide live in -[`tools/gmail/search-queries.md`](../../../tools/gmail/search-queries.md#security-import-issues--prior-rejection-search); +[`tools/gmail/search-queries.md`](../../../tools/gmail/search-queries.md#security-issue-import--prior-rejection-search); in short: **Backend selection.** When PonyMail MCP is enabled and @@ -628,7 +628,7 @@ Decide the candidate's class from the root message: |---|---|---| | **Report**: a reporter describes a vulnerability | The body has a description, a PoC / reproduction steps, an impact claim. Sender is an external address (not `@apache.org`, not on the security-team roster in [`AGENTS.md`](../../../AGENTS.md)). | Proceed to Step 4. | | **ASF-security relay**: `security@apache.org` forwarded a report from a reporter via the Foundation channel | Sender is `security@apache.org`. The body almost always starts with the ASF forwarding preamble — *"Dear PMC, The security vulnerability report has been received by the Apache Security Team and is being passed to you for action …"* — and contains the original report underneath (often after a `====GHSA-…` separator when the report came in via GitHub Security Advisory). The preamble is the load-bearing signal: if you see it, treat as a report regardless of what follows. | Proceed to Step 4. **Credit extraction**: the forwarded body usually ends with a `Credit` line naming the discoverer (e.g. *"This vulnerability was discovered and reported by bugbunny.ai"*) — use that verbatim for the Reporter-credited-as placeholder, not the `From:` header (which is always `security@apache.org`). If the report has no credit line, fall back to the GHSA number or to the phrase *"ASF-relayed"* so the credit-preference question can be routed through `@raboof` / Arnout. | -| **CVE-tool bookkeeping**: an automated or human status-change notification on the ASF CVE tool | Sender is `security@apache.org` (or one of the security-team members acting on behalf of the CVE tool). Subject matches one of: `"CVE-YYYY-NNNNN reserved for airflow"`, `"Comment added on CVE-YYYY-NNNNN"`, `"CVE-YYYY-NNNNN is now READY"`, `"CVE-YYYY-NNNNN is now PUBLIC"`, `"CVE-YYYY-NNNNN is now PUBLISHED"`, `"CVE-YYYY-NNNNN REJECTED"`, or a verbatim `""` line in the body pointing at `cveprocess.apache.org/cve5/CVE-YYYY-NNNNN`. | Do **not** import and do **not** draft a reply — the CVE-tool notifications are consumed by the `security-sync-issues` skill's Step 1e review-comment check. Classify as `cve-tool-bookkeeping` and drop. | +| **CVE-tool bookkeeping**: an automated or human status-change notification on the ASF CVE tool | Sender is `security@apache.org` (or one of the security-team members acting on behalf of the CVE tool). Subject matches one of: `"CVE-YYYY-NNNNN reserved for airflow"`, `"Comment added on CVE-YYYY-NNNNN"`, `"CVE-YYYY-NNNNN is now READY"`, `"CVE-YYYY-NNNNN is now PUBLIC"`, `"CVE-YYYY-NNNNN is now PUBLISHED"`, `"CVE-YYYY-NNNNN REJECTED"`, or a verbatim `""` line in the body pointing at `cveprocess.apache.org/cve5/CVE-YYYY-NNNNN`. | Do **not** import and do **not** draft a reply — the CVE-tool notifications are consumed by the `security-issue-sync` skill's Step 1e review-comment check. Classify as `cve-tool-bookkeeping` and drop. | | **Automated scanner dump**: SAST/DAST tool output, CodeQL/Dependabot alert paste, a string of "issues" with no human PoC | Body is machine-generated, contains multiple unrelated findings, no explanation of Security Model violation | Surface as a candidate with class `automated-scanner` and **do not** propose auto-import. In Step 5 the skill proposes a Gmail draft from the *"Automated scanning results"* canned response in [`canned-responses.md`](../../..//canned-responses.md) instead. | | **Consolidated multi-issue report**: one email bundles ≥3 unrelated vulnerabilities | The root message has headings like *"Issue 1"*, *"Issue 2"*, each of which would be its own tracker | Surface class `consolidated-multi-issue`; do not auto-import. Propose the "Sending multiple issues in consolidated report" canned reply. | | **Media / research-disclosure request**: reporter wants to publish a blog or talk about a finding we already know about | Body asks about disclosure timing, mentions a talk / blog / CVE on another vendor | Surface class `media-request`; do not auto-import. Propose the "When someone submits a media report" canned reply. | @@ -648,7 +648,7 @@ is missing a vulnerability. For each `Report` / `ASF-security relay` candidate, extract the fields the [issue template](../../../.github/ISSUE_TEMPLATE/issue_report.yml) expects. Most fields the reporter did not explicitly supply stay as -`_No response_`; the subsequent `security-sync-issues` run will prompt +`_No response_`; the subsequent `security-issue-sync` run will prompt the triager to fill them as the discussion progresses. The generic body-field schema (role → field-name contract, empty-field @@ -665,11 +665,11 @@ here. | **The issue description** | The root email body, **verbatim** (preserve paragraphs, PoC code blocks, and any quoted sections). The body is private — the triager will copy it into a public CVE description only after Step 13. | | **Short public summary for publish** | Leave `_No response_`. Filled by the release manager at Step 13 in sanitised form. | | **Affected versions** | Extract `Airflow ` / `>= X, < Y` / `/project.md`](../../..//project.md#gmail-and-ponymail). Propose the constructed search URL to the user at Step 5, wait for them to paste back the resolved `lists.apache.org/thread/?` URL, and record both the PonyMail URL and the Gmail `threadId` in this field. The URL is **internal-only** — the `generate-cve-json` script will not export it to `references[]` — see the "CVE references must never point at non-public mailing-list threads" section of [`AGENTS.md`](../../../AGENTS.md). | -| **Public advisory URL** | `_No response_`. Populated at Step 14 by `security-sync-issues` once the advisory is archived. | +| **Security mailing list thread** | **Keep the private thread handle, and — if possible — also link the PonyMail archive entry.** The full URL-construction recipe (search URL template, month-token format, user-pastes-back flow, Gmail-threadId fallback) lives in [`tools/gmail/ponymail-archive.md`](../../../tools/gmail/ponymail-archive.md#use-case--security-issue-import); the adopting project's private-search URL template is declared in [`/project.md`](../../..//project.md#gmail-and-ponymail). Propose the constructed search URL to the user at Step 5, wait for them to paste back the resolved `lists.apache.org/thread/?` URL, and record both the PonyMail URL and the Gmail `threadId` in this field. The URL is **internal-only** — the `generate-cve-json` script will not export it to `references[]` — see the "CVE references must never point at non-public mailing-list threads" section of [`AGENTS.md`](../../../AGENTS.md). | +| **Public advisory URL** | `_No response_`. Populated at Step 14 by `security-issue-sync` once the advisory is archived. | | **Reporter credited as** | The reporter's full display name from the email `From:` header (e.g. `Alice Example` from `"Alice Example" `). This is a **placeholder** — the receipt-of-confirmation reply in Step 7 asks the reporter to confirm their preferred credit form. | | **PR with the fix** | `_No response_`. | -| **Remediation developer** | `_No response_`. Auto-populated by the `security-sync-issues` skill from the linked PR's author the first time *PR with the fix* is set; manual edits are preserved on subsequent syncs. | +| **Remediation developer** | `_No response_`. Auto-populated by the `security-issue-sync` skill from the linked PR's author the first time *PR with the fix* is set; manual edits are preserved on subsequent syncs. | | **CWE** | `_No response_`. The security team scores CWE independently; a reporter-supplied CWE is informational only (per the *"Reporter-supplied CVSS scores are informational only"* rule in [`AGENTS.md`](../../../AGENTS.md)). Do **not** copy a CWE from the reporter's body into this field. | | **Severity** | `Unknown`. Same reason as CWE — the team scores independently. Surface a reporter-supplied CVSS / severity label in the proposal's observed-state for context, but do not use it as the field value. | | **CVE tool link** | `_No response_`. Filled at Step 6 once the CVE is allocated. | @@ -704,7 +704,7 @@ Present all candidates as a single numbered proposal grouped by class: canned-response discipline below. - **Dropped silently** (class `cve-tool-bookkeeping`): do not even surface these to the user — they are consumed by - `security-sync-issues` Step 1e. The skill should just report the + `security-issue-sync` Step 1e. The skill should just report the count in the recap (*"N CVE-tool-bookkeeping emails dropped"*) so the user knows the filter is working but is not forced to scroll past them. @@ -1143,5 +1143,5 @@ before presenting. - [`canned-responses.md`](../../..//canned-responses.md) — the canned email bodies the skill uses for receipt-of-confirmation, invalid reports, automated scans, etc. -- [`security-sync-issues`](../security-sync-issues/SKILL.md) — the +- [`security-issue-sync`](../security-issue-sync/SKILL.md) — the follow-up skill that runs on the tracker this one creates. diff --git a/.claude/skills/security-invalidate-issue/SKILL.md b/.claude/skills/security-issue-invalidate/SKILL.md similarity index 96% rename from .claude/skills/security-invalidate-issue/SKILL.md rename to .claude/skills/security-issue-invalidate/SKILL.md index 3b44c8f8..d84cb307 100644 --- a/.claude/skills/security-invalidate-issue/SKILL.md +++ b/.claude/skills/security-issue-invalidate/SKILL.md @@ -1,5 +1,5 @@ --- -name: security-invalidate-issue +name: security-issue-invalidate description: | Close an `` tracking issue as invalid: apply the `invalid` label, remove the scope label, post a short closing @@ -8,7 +8,7 @@ description: | polite-but-firm reply to the reporter on the original Gmail thread explaining the team's reasoning (extracted from the tracker's discussion). For trackers opened via - `security-import-issue-from-pr`, the email-draft step is skipped + `security-issue-import-from-pr`, the email-draft step is skipped per the *no outreach to the PR author* rule of that skill. when_to_use: | Invoke when a security team member says "close NN as invalid", @@ -31,7 +31,7 @@ when_to_use: | Before running any bash command below, substitute these with the concrete values from the adopting project's /project.md. --> -# security-invalidate-issue +# security-issue-invalidate This skill is the **terminal-disposition apply step** for the `invalid` close on an `` tracker. It does not host the @@ -45,7 +45,7 @@ closes the tracker, archives the project-board item, and (for explaining why. It is the symmetric counterpart of -[`security-allocate-cve`](../security-allocate-cve/SKILL.md) (apply step for the +[`security-cve-allocate`](../security-cve-allocate/SKILL.md) (apply step for the *valid → CVE* path). Both skills assume the validity decision has already been reached; they wire that decision into the tracker state in one pass. @@ -66,7 +66,7 @@ material. **Golden rule — no outreach to PR-imported tracker authors.** When the tracker came in via -[`security-import-issue-from-pr`](../security-import-issue-from-pr/SKILL.md) +[`security-issue-import-from-pr`](../security-issue-import-from-pr/SKILL.md) (detected by the `N/A — opened from public PR …` sentinel in the *Security mailing list thread* body field), there is no reporter to notify — the PR author is not the CVE reporter and the public @@ -167,8 +167,8 @@ the close. Read the *Security mailing list thread* body field: | Body field shape | Import path | Email-draft step | |---|---|---| | Real `lists.apache.org` URL or any URL | `security@`-imported (public-archive case) | Draft on the original Gmail thread; locate via the rollup-comment `threadId` reference. | -| `No public archive URL — tracked privately on Gmail thread ` (sentinel from [`security-import-issues`](../security-import-issues/SKILL.md) Step 7) | `security@`-imported (Gmail-only case) | Draft on the named ``. | -| `N/A — opened from public PR #; no security@ thread` (sentinel from [`security-import-issue-from-pr`](../security-import-issue-from-pr/SKILL.md)) | PR-imported | **Skip** the email-draft step. No reporter exists to notify. | +| `No public archive URL — tracked privately on Gmail thread ` (sentinel from [`security-issue-import`](../security-issue-import/SKILL.md) Step 7) | `security@`-imported (Gmail-only case) | Draft on the named ``. | +| `N/A — opened from public PR #; no security@ thread` (sentinel from [`security-issue-import-from-pr`](../security-issue-import-from-pr/SKILL.md)) | PR-imported | **Skip** the email-draft step. No reporter exists to notify. | | Empty / `_No response_` / unrecognised | Indeterminate | Surface to the user; ask whether the tracker has a Gmail thread the skill should reply on, or whether the close is silent (no email). | For `security@`-imported trackers, locate the Gmail `threadId`: @@ -234,7 +234,7 @@ on the tracker), surface this gap to the user with: The email draft is built canned-response-spine + augmentation, same pattern as -[`security-import-issues` Step 5](../security-import-issues/SKILL.md). +[`security-issue-import` Step 5](../security-issue-import/SKILL.md). Read [`/canned-responses.md`](../../..//canned-responses.md) and pick the section that best matches the invalidity reasoning mined in Step 3: @@ -292,7 +292,7 @@ Reasoning summary in the [status rollup](#issuecomment-); a draft rep For PR-imported trackers, replace *"a draft reply to the reporter is in Gmail awaiting review"* with *"no reporter notification (PR-imported tracker — see the import-from-pr skill's -[Reporter credit policy](https://github.com//blob//.claude/skills/security-import-issue-from-pr/SKILL.md#reporter-credit-policy-for-public-pr-imports))"*. +[Reporter credit policy](https://github.com//blob//.claude/skills/security-issue-import-from-pr/SKILL.md#reporter-credit-policy-for-public-pr-imports))"*. The comment links must resolve once the rollup entry from Step 5e has been posted (capture its URL and substitute before posting @@ -357,7 +357,7 @@ For `security@`-imported trackers: ASF-security relay path (the `From:` is a `@apache.org` forwarder, not the external reporter), reply to the forwarder per the *ASF-security relay* convention in - [`security-import-issues` Step 7](../security-import-issues/SKILL.md). + [`security-issue-import` Step 7](../security-issue-import/SKILL.md). - `ccRecipients`: always includes `` (`` for the adopting project) — value comes from @@ -373,7 +373,7 @@ For `security@`-imported trackers: equivalent) with the case-specific reasoning gathered in Step 3. Use the same `> **[Inline addition for this report]**` block convention as - [`security-import-issues` Step 5](../security-import-issues/SKILL.md) + [`security-issue-import` Step 5](../security-issue-import/SKILL.md) — the user must be able to delete the augmentation cleanly without leaving a grammatical orphan. - **No mention of ``.** The tracker repo is @@ -420,7 +420,7 @@ upsert recipe). Shape: **Reporter notification:** - **`security@`-imported:** Gmail draft `` created on thread `` — awaiting user review. -- **PR-imported:** none (no reporter; per [Reporter credit policy](https://github.com//blob//.claude/skills/security-import-issue-from-pr/SKILL.md#reporter-credit-policy-for-public-pr-imports)). +- **PR-imported:** none (no reporter; per [Reporter credit policy](https://github.com//blob//.claude/skills/security-issue-import-from-pr/SKILL.md#reporter-credit-policy-for-public-pr-imports)). - **Indeterminate import path:** none (flag from Step 2 surfaced; user explicitly chose silent close). **Project board:** archived (item ``). @@ -453,7 +453,7 @@ entry — and ask: reporter is unreachable, GHSA closed, etc.). - `cancel` / `none` — bail; nothing applied. -The user must confirm explicitly. Unlike `security-import-issues`, +The user must confirm explicitly. Unlike `security-issue-import`, this skill does **not** default to apply — the close is a terminal disposition and the email draft is a public message attributed to the security team. One round of confirmation is @@ -639,7 +639,7 @@ invalidate 355 ``` Tracker `#355` (the public-PR-imported tracker from the test of -`security-import-issue-from-pr` against PR 65703). Suppose the +`security-issue-import-from-pr` against PR 65703). Suppose the team later decides the report is not CVE-worthy on its own merits. Step 2 detects the `N/A — opened from public PR` sentinel; the email-draft step is skipped. Closing comment notes *"no diff --git a/.claude/skills/security-sync-issues/SKILL.md b/.claude/skills/security-issue-sync/SKILL.md similarity index 99% rename from .claude/skills/security-sync-issues/SKILL.md rename to .claude/skills/security-issue-sync/SKILL.md index 35782050..a866ca09 100644 --- a/.claude/skills/security-sync-issues/SKILL.md +++ b/.claude/skills/security-issue-sync/SKILL.md @@ -1,5 +1,5 @@ --- -name: security-sync-issues +name: security-issue-sync description: | Synchronize a security issue in with the state of its GitHub discussion, the mailing thread, and any @@ -25,7 +25,7 @@ when_to_use: | Before running any bash command below, substitute these with the concrete values from the adopting project's /project.md. --> -# security-sync-issues +# security-issue-sync This skill reconciles a single security issue in [``](https://github.com/) with: @@ -484,7 +484,7 @@ Process for finding the real reporter and the original thread: phrase* from the issue body (a function name, an endpoint, an error message) and search Gmail with it, **excluding GitHub notifications**. The canonical query template for this search lives in - [`tools/gmail/search-queries.md`](../../../tools/gmail/search-queries.md#security-sync-issues--reporter-thread-lookup-by-distinctive-phrase) + [`tools/gmail/search-queries.md`](../../../tools/gmail/search-queries.md#security-issue-sync--reporter-thread-lookup-by-distinctive-phrase) (the GitHub-notification exclusions used for this project are declared in [`/project.md`](../../..//project.md#gmail-and-ponymail)). @@ -630,7 +630,7 @@ update, label change, or next-step recommendation in Step 2: | A tracker is transitioning to `fix released` (per the row below) and *"Affected versions"* still carries the project's pre-release sentinel | Propose replacing the sentinel with the concrete released version per the project's convention; see [`/scope-labels.md` — *Affected versions convention by scope*](../../..//scope-labels.md#affected-versions-convention-by-scope) for the recipe. After the body update, regenerate the CVE JSON attachment so `versions[]` picks up the bounded `lessThan` shape and the record becomes review-ready. | | A release carrying the fix has shipped. Detection is **scope-dependent** — different scope labels on a project can ride different release trains, each with its own *"is it released?"* signal (which artifact registry to consult, what to query, how to map a tracker's milestone to that registry, partial-release edge cases). The per-scope detection recipe lives in [`/scope-labels.md` — *Detecting that a fix release has shipped*](../../..//scope-labels.md#detecting-that-a-fix-release-has-shipped). The "or an explicit *fix shipped in X.Y.Z* comment" fallback applies across all scopes regardless of the project-specific signal. | Propose swapping `pr merged` → `fix released` (Step 12). This is the release manager's cue to own Steps 13–15 (advisory send → URL capture → Vulnogram PUBLIC → close). **Also propose swapping the assignee from the remediation developer to the release manager** (looked up via the three-source cascade in Step 2c — [`/release-trains.md`](../../..//release-trains.md) "Release managers for releases currently relevant to the security tracker" → Release Plan wiki → `[RESULT][VOTE]` thread on `dev@`), so the issue list reflects ownership hand-off. See the *Assignee hand-off at the `fix released` transition* paragraph under **Assignees** in Step 2b for the full rule. | | GHSA state transition (opened, accepted, published, rejected) in a GHSA-forwarded email | If the GHSA is closed as "not accepted" but the security team accepted the report on `security@`, flag the divergence in the status comment so it is not lost. | -| Team member saying *"let's also backport to v3-2-test"* / *"please mark X for backport"* | Note the requested backport label on the public PR as an item for Step 9 of the `security-fix-issue` workflow. | +| Team member saying *"let's also backport to v3-2-test"* / *"please mark X for backport"* | Note the requested backport label on the public PR as an item for Step 9 of the `security-issue-fix` workflow. | | Reporter flagging a second distinct vulnerability on the same thread | Surface as an explicit question to the user — it may warrant a separate tracking issue. | | Team member classifying severity or CWE independently (not copying the reporter) | Propose setting the `Severity` / `CWE` fields accordingly, with a pointer to the comment that established the assessment. | | Stale "pending" text from an earlier status update (e.g. the tracker still says *"CVE allocation pending"* but the issue body now has a CVE) | Propose removing the stale reference from the status-change comment trail. | @@ -699,7 +699,7 @@ fallback when (a) PonyMail is not enabled / not authenticated, before the archive indexes it. **Search recipe.** Use the CVE-review-comment query templates in -[`tools/gmail/search-queries.md`](../../../tools/gmail/search-queries.md#security-sync-issues--cve-review-comment-search); +[`tools/gmail/search-queries.md`](../../../tools/gmail/search-queries.md#security-issue-sync--cve-review-comment-search); substitute the adopting project's `` (Airflow: ``, declared in [`/project.md`](../../..//project.md#gmail-and-ponymail)) @@ -866,7 +866,7 @@ the recipe lives in Concretely, for each closed-`announced` tracker in this run: 1. Extract the `CVE-YYYY-NNNNN` ID from the tracker's *CVE tool - link* body field (same field the security-allocate-cve and sync skills + link* body field (same field the security-cve-allocate and sync skills already read). 2. Call the API: ```bash @@ -1093,7 +1093,7 @@ will change and *why*. Group them by category: - **PonyMail HTTP API (fallback).** When PonyMail MCP is disabled, unauthenticated, or returns an error, fall back to the HTTP API + `list.html` pattern documented in - [`tools/gmail/ponymail-archive.md`](../../../tools/gmail/ponymail-archive.md#use-case--security-sync-issues). + [`tools/gmail/ponymail-archive.md`](../../../tools/gmail/ponymail-archive.md#use-case--security-issue-sync). The adopting project's URL templates are declared in [`/project.md`](../../..//project.md#gmail-and-ponymail) (`ponymail_api_url_template`, @@ -1286,9 +1286,9 @@ will change and *why*. Group them by category: **The status record lives in a single rollup comment, not a new comment per sync.** The first bot-authored comment on a tracker is the **rollup comment** (created by the - [`security-import-issues`](../security-import-issues/SKILL.md) - skill); every subsequent pass — this sync skill, security-allocate-cve, - security-deduplicate-issues, security-fix-issue — appends a new + [`security-issue-import`](../security-issue-import/SKILL.md) + skill); every subsequent pass — this sync skill, security-cve-allocate, + security-issue-deduplicate, security-issue-fix — appends a new *entry* to that comment instead of posting a fresh one. Readers scroll one comment instead of fifteen. The full shape, summary conventions, upsert recipe, and legacy-comment-folding rules @@ -1394,7 +1394,7 @@ will change and *why*. Group them by category: `**Closing as duplicate`, `**Split for scope clarity`, `**Imported on `, `**Process-step escalation`, `**Allocated CVE`, or the bare-text `Sync status (` / `Sync YYYY-MM-DD` / `Status update` - legacy prefixes, or a content tell like `security-sync-issues + legacy prefixes, or a content tell like `security-issue-sync skill`). For each hit, the Step 2 proposal carries a numbered item: *"fold legacy comment `` (``, first line ) into the rollup as a `` entry, then @@ -1591,7 +1591,7 @@ updates land, based on the process step. Examples: - *"Step 3: start the CVE-worthiness discussion in a comment on the issue, tagging at least one other security team member."* - *"Step 4: escalate to a wider audience — the discussion has been stalled for 34 days. Run the two-phase escalation per [`README.md` — Step 4](../../../README.md#step-4--escalate-stalled-discussions): phase 1 is a short call for ideas to `` (no AI analysis), phase 2 — only if phase 1 stays silent for ~7 more days — is an AI-generated design-space analysis that the triager reviews before posting. The agent drafts both phases as proposals; the triager confirms the exact wording + the list of people to `@`-mention before anything is sent."* -- *"Step 6: allocate a CVE. Run the [`security-allocate-cve`](../security-allocate-cve/SKILL.md) skill (it prints the ASF Vulnogram form URL plus a CVE-ready title and wires the allocated ID back into the tracker)."* +- *"Step 6: allocate a CVE. Run the [`security-cve-allocate`](../security-cve-allocate/SKILL.md) skill (it prints the ASF Vulnogram form URL plus a CVE-ready title and wires the allocated ID back into the tracker)."* - *"Step 10: close the private PR at #NNN now that #NNNN has merged."* - *"Step 11: `pr merged` — tracker parked until the release train ships. No action needed from the security team; the next sync run will detect the PyPI / Helm release and propose the `fix released` swap (Step 12)."* - *"Step 12: `fix released` — the release carrying the fix is now on PyPI / the Helm registry. Ownership of the issue has transferred to the release manager; the label swap was the hand-off."* @@ -1658,10 +1658,10 @@ wrong name in a status update leads to the advisory sitting on nobody's desk. **If a CVE needs to be allocated**, always point the user at the -[`security-allocate-cve`](../security-allocate-cve/SKILL.md) skill explicitly on its own +[`security-cve-allocate`](../security-cve-allocate/SKILL.md) skill explicitly on its own line so the handoff is unambiguous: -> Allocate a CVE via the [`security-allocate-cve`](../security-allocate-cve/SKILL.md) +> Allocate a CVE via the [`security-cve-allocate`](../security-cve-allocate/SKILL.md) > skill. It opens the ASF Vulnogram form at > , pre-computes a CVE-ready > title (stripped of `: :` (e.g. `Apache Airflow:`) / `[ Security Report ]` / version diff --git a/.claude/skills/setup-secure-config/SKILL.md b/.claude/skills/setup-isolated-setup-install/SKILL.md similarity index 92% rename from .claude/skills/setup-secure-config/SKILL.md rename to .claude/skills/setup-isolated-setup-install/SKILL.md index c09318ff..f061f93f 100644 --- a/.claude/skills/setup-secure-config/SKILL.md +++ b/.claude/skills/setup-isolated-setup-install/SKILL.md @@ -1,5 +1,5 @@ --- -name: setup-secure-config +name: setup-isolated-setup-install description: | Guide an adopter through the first-time install of the framework's secure agent setup — pinned system tools (`bubblewrap`, `socat`, @@ -21,8 +21,8 @@ when_to_use: | secure-config wiring yet. Also appropriate after a fresh OS install / new dev machine where `~/.claude/scripts/` is empty. Do **not** invoke when the secure setup is already in place — use - `setup-verify-secure-config` (to confirm completeness) or - `setup-update-secure-config` (to refresh against the framework's + `setup-isolated-setup-verify` (to confirm completeness) or + `setup-isolated-setup-update` (to refresh against the framework's latest) instead. --- @@ -31,7 +31,7 @@ when_to_use: | → value of `tracker_repo:` in /project.md → value of `upstream_repo:` in /project.md --> -# setup-secure-config +# setup-isolated-setup-install This skill is the **on-ramp** for adopters who do not yet have the secure setup running. It is a thin walkthrough wrapper around the @@ -102,23 +102,23 @@ sub-step with the user. The doc names are the source of truth; the skill is the runner. For the verification step at the end, hand off to the -`setup-verify-secure-config` skill rather than re-walking the checklist +`setup-isolated-setup-verify` skill rather than re-walking the checklist inline. ## After the install lands Suggest two follow-up routines the user can wire later: -- `setup-verify-secure-config` — re-run after every Claude Code upgrade +- `setup-isolated-setup-verify` — re-run after every Claude Code upgrade or settings-file edit, to confirm denials still fire as expected. The "did a denial silently turn into an allow?" signal is exactly what this skill exists for. -- `setup-update-secure-config` — periodic check for framework +- `setup-isolated-setup-update` — periodic check for framework updates, pinned-tool upgrade candidates, and drift between the installed user-scope copies and the framework's source-of-truth. Recommend a per-Claude-Code-upgrade or monthly cadence, whichever comes first. If the user has the `~/.claude-config` sync repo in place, also -mention `setup-sync-shared-config` for committing + pushing local +mention `setup-shared-config-sync` for committing + pushing local modifications to the shared scripts. diff --git a/.claude/skills/setup-update-secure-config/SKILL.md b/.claude/skills/setup-isolated-setup-update/SKILL.md similarity index 94% rename from .claude/skills/setup-update-secure-config/SKILL.md rename to .claude/skills/setup-isolated-setup-update/SKILL.md index b6cdd4eb..70ca9498 100644 --- a/.claude/skills/setup-update-secure-config/SKILL.md +++ b/.claude/skills/setup-isolated-setup-update/SKILL.md @@ -1,5 +1,5 @@ --- -name: setup-update-secure-config +name: setup-isolated-setup-update description: | Surface drift between the user's installed secure agent setup and the framework's latest. Reports framework-checkout updates @@ -24,7 +24,7 @@ when_to_use: | -# setup-update-secure-config +# setup-isolated-setup-update This skill is the **drift report** for an already-installed secure setup. It walks the canonical update-check at @@ -39,7 +39,7 @@ any change. `npm install -g`, does not modify the user's shell rc. It reports drift and points at the doc / the install skill; the user runs the actual updates by hand or by re-invoking - `setup-secure-config` for the touched piece. + `setup-isolated-setup-install` for the touched piece. - **Surface upstream changelog links.** For every pinned-tool upgrade candidate, include the upstream changelog / release- notes URL so the user can read the diff before deciding. A @@ -55,7 +55,7 @@ any change. changes into `~/.claude-config/scripts/`). Report each separately. - **Re-verify after surfacing the drift.** Run the same denial - checks `setup-verify-secure-config` runs (one Bash invocation per + checks `setup-isolated-setup-verify` runs (one Bash invocation per command, not chained), so a regression that turned a deny into an allow shows up as part of the update report. A *passing* verification at the end of an update report is the signal that @@ -100,7 +100,7 @@ Walk each: the user does not have; do not auto-merge. 5. **Re-verify.** Run the three denial commands as standalone Bash invocations (not chained — see - [setup-verify-secure-config](../setup-verify-secure-config/SKILL.md) for + [setup-isolated-setup-verify](../setup-isolated-setup-verify/SKILL.md) for why). Report any newly-allowed call as a regression that warrants attention. @@ -113,7 +113,7 @@ If something is out-of-date or has drifted, name the concrete follow-up: - Framework checkout behind → run - [`setup-upgrade-steward`](../setup-upgrade-steward/SKILL.md), + [`setup-steward-upgrade`](../setup-steward-upgrade/SKILL.md), which performs the `git pull --ff-only` after the same pre-flight checks this skill recommends, surfaces what arrived, and reminds the user to handle the parent-tracker @@ -123,7 +123,7 @@ follow-up: - User-scope script drift → re-`cp` from the framework checkout, or — if the script lives in `~/.claude-config/` and the user wants the change propagated to other machines — invoke - `setup-sync-shared-config` to commit + push. + `setup-shared-config-sync` to commit + push. - Settings.json shape drift → the user merges the new framework block into their tracker's `.claude/settings.json` by hand (the section to copy from is documented in diff --git a/.claude/skills/setup-verify-secure-config/SKILL.md b/.claude/skills/setup-isolated-setup-verify/SKILL.md similarity index 92% rename from .claude/skills/setup-verify-secure-config/SKILL.md rename to .claude/skills/setup-isolated-setup-verify/SKILL.md index 850cadc0..34bdd134 100644 --- a/.claude/skills/setup-verify-secure-config/SKILL.md +++ b/.claude/skills/setup-isolated-setup-verify/SKILL.md @@ -1,5 +1,5 @@ --- -name: setup-verify-secure-config +name: setup-isolated-setup-verify description: | Walk the verification checklist documented in `secure-agent-setup.md` and report ✓ done / ✗ missing / ⚠ partial @@ -13,7 +13,7 @@ when_to_use: | Invoke when the user says "verify my secure setup", "is my secure config done?", "check that the secure agent setup is installed", "did setup work?", or after running - `setup-secure-config` to confirm the install landed completely. + `setup-isolated-setup-install` to confirm the install landed completely. Also appropriate as a routine — after every Claude Code upgrade, after every project / user-scope `settings.json` edit, and any time a previously-blocked Bash call appears to have succeeded @@ -24,7 +24,7 @@ when_to_use: | -# setup-verify-secure-config +# setup-isolated-setup-verify This skill is the **assertion** layer over the secure setup. It runs the checklist documented in @@ -37,8 +37,8 @@ and reports each check's status to the user with concrete evidence - **Read-only.** This skill does not edit any file, copy any script, install any package, or modify any settings. If a check surfaces a missing or misconfigured piece, surface the gap and - point at the install path (`setup-secure-config` for a missing - install, `setup-update-secure-config` for drift); do not auto-fix. + point at the install path (`setup-isolated-setup-install` for a missing + install, `setup-isolated-setup-update` for drift); do not auto-fix. - **Report every check, even on early failure.** Do not stop at the first ✗ — the value of the report is in the full picture. If check 3 fails, continue to checks 4 / 5 / 6 / 7 anyway and @@ -111,11 +111,11 @@ suggestion needed. If anything is ✗ or ⚠, suggest the appropriate follow-up skill without invoking it: -- ✗ on checks 1 / 2 / 3 / 4 → `setup-secure-config` (missing +- ✗ on checks 1 / 2 / 3 / 4 → `setup-isolated-setup-install` (missing install pieces). - ⚠ on check 5 (pinned-version drift) or any user-scope script copy that is older than the framework's source-of-truth → - `setup-update-secure-config`. + `setup-isolated-setup-update`. - The user-scope script copies live under `~/.claude-config/` for users who maintain that sync repo; uncommitted local edits - there → `setup-sync-shared-config`. + there → `setup-shared-config-sync`. diff --git a/.claude/skills/setup-sync-shared-config/SKILL.md b/.claude/skills/setup-shared-config-sync/SKILL.md similarity index 98% rename from .claude/skills/setup-sync-shared-config/SKILL.md rename to .claude/skills/setup-shared-config-sync/SKILL.md index 6800e2ae..477e4064 100644 --- a/.claude/skills/setup-sync-shared-config/SKILL.md +++ b/.claude/skills/setup-shared-config-sync/SKILL.md @@ -1,5 +1,5 @@ --- -name: setup-sync-shared-config +name: setup-shared-config-sync description: | Commit + push the user's shared Claude config to the `~/.claude-config` private dotfile-style sync repo (per @@ -18,7 +18,7 @@ when_to_use: | `~/.claude-config/scripts/*.sh`, `~/.claude-config/CLAUDE.md`, `~/.claude-config/commands/*`, the `sync.sh` itself, etc. Also - appropriate after the `setup-update-secure-config` skill surfaces + appropriate after the `setup-isolated-setup-update` skill surfaces drift on a script that the user keeps in `~/.claude-config/` and the user wants the framework's update propagated to every machine the sync repo is checked out on. @@ -27,7 +27,7 @@ when_to_use: | -# setup-sync-shared-config +# setup-shared-config-sync This skill propagates local edits in `~/.claude-config/` to the sync repo's remote, so other machines can pull them. It is the diff --git a/.claude/skills/setup-upgrade-steward/SKILL.md b/.claude/skills/setup-steward-upgrade/SKILL.md similarity index 93% rename from .claude/skills/setup-upgrade-steward/SKILL.md rename to .claude/skills/setup-steward-upgrade/SKILL.md index 3d515304..082fd691 100644 --- a/.claude/skills/setup-upgrade-steward/SKILL.md +++ b/.claude/skills/setup-steward-upgrade/SKILL.md @@ -1,5 +1,5 @@ --- -name: setup-upgrade-steward +name: setup-steward-upgrade description: | Pull the user's local `airflow-steward` framework checkout to the latest `origin/main` and surface what changed — the commits @@ -8,7 +8,7 @@ description: | `secure-agent-setup.md`, `secure-agent-internals.md`, `pinned-versions.toml`), and the next-step recommendation. Never applies user-side propagation itself — that is the job of - `setup-update-secure-config` (drift report) and the framework + `setup-isolated-setup-update` (drift report) and the framework maintainer's manual re-`cp` of any user-scope script copies that drifted. Refuses to act if the working tree is dirty or the branch has unpushed commits, since both states are signs the @@ -21,8 +21,8 @@ when_to_use: | to a periodic update routine — recommended cadence per secure-agent-setup.md is once per Claude Code upgrade or once a month, whichever comes first; this skill is the *first* step - of that routine, with `setup-update-secure-config` (read-only drift - report) and any subsequent re-`cp` / `/setup-sync-shared-config` runs + of that routine, with `setup-isolated-setup-update` (read-only drift + report) and any subsequent re-`cp` / `/setup-shared-config-sync` runs following on. Do **not** invoke when the user has uncommitted changes in the framework checkout or when they have local commits ahead of origin — the skill will refuse and surface @@ -32,7 +32,7 @@ when_to_use: | -# setup-upgrade-steward +# setup-steward-upgrade This skill is the **upstream** half of the framework's update flow. It moves the user's local `airflow-steward` checkout forward to @@ -40,7 +40,7 @@ It moves the user's local `airflow-steward` checkout forward to this upgrade means for the user's *installed* secure setup (user-scope script copies, project `.claude/settings.json`, pinned tool versions on the host) — is the -[`setup-update-secure-config`](../setup-update-secure-config/SKILL.md) skill, +[`setup-isolated-setup-update`](../setup-isolated-setup-update/SKILL.md) skill, which is read-only and runs naturally as the next step. ## Golden rules @@ -78,7 +78,7 @@ which is read-only and runs naturally as the next step. `~/.claude/`. It does not edit any project's `.claude/settings.json`. It does not bump installed tool versions on the host. All of those are surfaced by the - follow-on `setup-update-secure-config` skill, which is read-only by + follow-on `setup-isolated-setup-update` skill, which is read-only by design — the user decides what to apply. ## Walk-through @@ -145,13 +145,13 @@ which is read-only and runs naturally as the next step. the new framework. Mention the post-merge hook documented in `README.md → Adopting the framework` for users who want this automatic. Suggest - [`setup-verify-steward`](../setup-verify-steward/SKILL.md) + [`setup-steward-verify`](../setup-steward-verify/SKILL.md) to confirm the parent tracker's submodule integration is still aligned (the skill catches the `+` "submodule HEAD ahead of parent index" state directly). - **Always after a successful pull**, recommend - [`setup-update-secure-config`](../setup-update-secure-config/SKILL.md) + [`setup-isolated-setup-update`](../setup-isolated-setup-update/SKILL.md) to surface user-side drift the upgrade may have introduced (new `permissions.deny` patterns the user's tracker repo hasn't picked up, drift between user-scope `~/.claude/` @@ -165,7 +165,7 @@ which is read-only and runs naturally as the next step. re-`cp`'ing the updated framework scripts over the `~/.claude-config/scripts/` (or `~/.claude/agent-isolation/`) copies and then running - [`setup-sync-shared-config`](../setup-sync-shared-config/SKILL.md) to + [`setup-shared-config-sync`](../setup-shared-config-sync/SKILL.md) to push the propagated changes to the sync remote so other machines pick them up. @@ -195,7 +195,7 @@ which is read-only and runs naturally as the next step. [Bumping a pinned version](../../../secure-agent-setup.md#bumping-a-pinned-version) flow. - Not for syncing user-scope edits to `~/.claude-config`. That - is `setup-sync-shared-config`'s job. + is `setup-shared-config-sync`'s job. ## Failure modes diff --git a/.claude/skills/setup-verify-steward/SKILL.md b/.claude/skills/setup-steward-verify/SKILL.md similarity index 95% rename from .claude/skills/setup-verify-steward/SKILL.md rename to .claude/skills/setup-steward-verify/SKILL.md index 586a5f27..b0d36107 100644 --- a/.claude/skills/setup-verify-steward/SKILL.md +++ b/.claude/skills/setup-steward-verify/SKILL.md @@ -1,5 +1,5 @@ --- -name: setup-verify-steward +name: setup-steward-verify description: | Verify that the `apache-steward` framework is correctly integrated into the user's adopter tracker repository — `.apache-steward/` @@ -31,7 +31,7 @@ when_to_use: | -# setup-verify-steward +# setup-steward-verify This skill is the **integration check** for adopters who consume the `apache-steward` framework as a git submodule of their @@ -41,11 +41,11 @@ It confirms the framework is wired in correctly so the rest of the framework's skills and tools resolve from the right paths. The companion skill is -[`setup-verify-secure-config`](../setup-verify-secure-config/SKILL.md), which +[`setup-isolated-setup-verify`](../setup-isolated-setup-verify/SKILL.md), which verifies the *secure-agent setup* (sandbox, hooks, status line, clean-env wrapper). The two are independent: an adopter can have the framework correctly integrated as a submodule but no secure -setup wired (setup-verify-secure-config catches that), or have the +setup wired (setup-isolated-setup-verify catches that), or have the secure setup wired against a stale / un-init'd framework submodule (this skill catches that). Run both for a complete adopter-side health check. @@ -125,7 +125,7 @@ inside `project.md` to enumerate unfilled fields. Distinguish: - ⚠ for unfilled fields that are convenience-only or apply only to optional flows — mailing-list addresses (only the import / sync skills need them), CVE tooling URLs (only - the security-allocate-cve skill), Gmail / PonyMail OAuth flags + the security-cve-allocate skill), Gmail / PonyMail OAuth flags (only the email-using skills). Print the unfilled-field list with line numbers so the user @@ -183,7 +183,7 @@ output. The leading character classifies the state: - `+` prefix = the submodule's `HEAD` is *ahead of* the SHA recorded in the parent's index. The user has either pulled the framework directly without committing the new pointer - in the parent (`setup-upgrade-steward` skill mentions this + in the parent (`setup-steward-upgrade` skill mentions this case), or has hand-checked-out a different SHA. Surface as ⚠ — the framework still works, but the parent will record a different pointer on the next commit. Remediation: commit @@ -231,7 +231,7 @@ step list, ordered most → least urgent: - ⚠ on check 5 (`+` prefix, pointer ahead) → name the remediation choice (commit the new pointer in the parent, or reset the submodule). The - [`setup-upgrade-steward`](../setup-upgrade-steward/SKILL.md) + [`setup-steward-upgrade`](../setup-steward-upgrade/SKILL.md) skill is the natural place this state usually originates. - ⚠ on check 6 (no post-merge hook) → print the install recipe and tell the user this is optional ergonomics. @@ -240,7 +240,7 @@ step list, ordered most → least urgent: them when the user adopts those skills. Recommend -[`setup-verify-secure-config`](../setup-verify-secure-config/SKILL.md) as +[`setup-isolated-setup-verify`](../setup-isolated-setup-verify/SKILL.md) as the natural next-step skill if the user has not run it yet — the two skills are independent but together cover the adopter-side health check. diff --git a/AGENTS.md b/AGENTS.md index 4749d727..f8511a9a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -322,7 +322,7 @@ and the failure mode is silent. Make `git submodule update --init into a post-merge hook (`.git/hooks/post-merge` → `#!/bin/sh\nexec git submodule update --init --recursive`). Same rule applies to the framework's own -[`setup-upgrade-steward`](.claude/skills/setup-upgrade-steward/SKILL.md) +[`setup-steward-upgrade`](.claude/skills/setup-steward-upgrade/SKILL.md) skill: when invoked from inside an adopter tracker, it reminds the user to follow up with submodule update on the parent. @@ -505,7 +505,7 @@ When editing or generating any text destined for a public audience, the load-bearing scrub is for **content** that came from the tracker (severity scores, CWE assignments, label transitions, comment quotes), not for the URL itself. The -`security-fix-issue` skill's pre-push grep follows this convention +`security-issue-fix` skill's pre-push grep follows this convention — it warns on `CVE-`, *"security fix"*, *"vulnerability"*, *"advisory"*, and verbatim-content patterns, but it does **not** flag a bare `` URL or `#NNN` reference on its own. @@ -680,7 +680,7 @@ Concretely, the issue template has two separate fields for this: been sent (Step 13 of the process). This is the URL that ends up as the `vendor-advisory` reference on the public CVE record. Before the advisory is sent the field stays empty; the - `security-sync-issues` skill scans the users-list archive for the + `security-issue-sync` skill scans the users-list archive for the CVE ID and proposes populating the field automatically once the advisory lands. @@ -794,11 +794,11 @@ them is a **request or a fact**, not a briefing: patience…"). A plain *"Thanks,"* / *"Regards,"* is enough. - Any open question that was already asked on the thread and is still awaiting a reply (see the "Do not re-ask" rule in the - `security-sync-issues` skill — pinging twice gets us blocklisted). + `security-issue-sync` skill — pinging twice gets us blocklisted). **Exception: the initial receipt-of-confirmation reply.** The first message the security team sends to a new reporter, drafted by the -`security-import-issues` skill, uses the *"Confirmation of receiving +`security-issue-import` skill, uses the *"Confirmation of receiving the report"* canned response from [`/canned-responses.md`](/canned-responses.md) **verbatim**. That template is longer because it introduces the process @@ -830,7 +830,7 @@ directly. The drafting rules for that case — different `To:`, same threading behaviour (prefer `threadId`, fall back to the inbound subject), terse body — live in [`tools/gmail/asf-relay.md`](tools/gmail/asf-relay.md). The detection -signals the `security-import-issues` skill uses to classify a candidate +signals the `security-issue-import` skill uses to classify a candidate as a relay live in that skill's Step 3. ### Point reporters to the project's Security Model, don't re-explain it @@ -853,7 +853,7 @@ repository) rather than duplicated in the canned responses. Whenever a CVE ID appears in text this repository produces — status comments on `` issues, proposals from the -`security-sync-issues` skill, recap messages, canned-response drafts +`security-issue-sync` skill, recap messages, canned-response drafts to reporters, internal notes — render it as a **clickable link**, not as bare text. The canonical link is the adopting project's CVE-tool record URL, which any security team member can click through to the @@ -994,7 +994,7 @@ reporter emails, advisory references). What still must not appear publicly is the *contents* the link points at — comment quotes, labels, body excerpts, severity assessments — and, before the advisory ships, the security framing of the change. The scrubbing -grep the `security-fix-issue` skill runs before pushing anything +grep the `security-issue-fix` skill runs before pushing anything public flags content leaks (CVE IDs, *"vulnerability"*, *"security fix"* phrasing, verbatim tracker quotes); a bare tracker URL or `#NNN` reference on its own does not trigger the scrub. @@ -1024,7 +1024,7 @@ in The authoritative roster and the release-manager rotation list live in [`/release-trains.md`](/release-trains.md). -The security-sync-issues and security-fix-issue skills should render +The security-issue-sync and security-issue-fix skills should render every maintainer / security-team / release-manager reference in the status comments they post as an `@` handle. Before publishing a status comment, the skills must grep for names of known people and flag any @@ -1052,7 +1052,7 @@ commit message or an ad-hoc comment. Currently available: -- [`security-import-issues`](.claude/skills/security-import-issues/SKILL.md) — +- [`security-issue-import`](.claude/skills/security-issue-import/SKILL.md) — the on-ramp of the process. Scans `` for threads that have not yet been copied into `` as tracking issues, classifies each candidate (real report vs. automated-scan / consolidated / @@ -1065,7 +1065,7 @@ Currently available: Gmail `threadId`. This is Step 2 of the handling process in [`README.md`](README.md) and the first skill a triager runs in a morning sweep. -- [`security-deduplicate-issues`](.claude/skills/security-deduplicate-issues/SKILL.md) — +- [`security-issue-deduplicate`](.claude/skills/security-issue-deduplicate/SKILL.md) — merges two tracking issues that describe the same root-cause vulnerability discovered independently by different reporters. Copies the dropped tracker's body verbatim into the kept tracker as a @@ -1074,15 +1074,15 @@ Currently available: tracker's CVE JSON attachment so both finders land in `credits[]`, and closes the dropped tracker with the `duplicate` label. Refuses to operate across different scope labels (those require a scope split - via `security-sync-issues`, not a dedupe). Typically invoked after - `security-import-issues` Step 2a surfaces a STRONG GHSA-ID match with + via `security-issue-sync`, not a dedupe). Typically invoked after + `security-issue-import` Step 2a surfaces a STRONG GHSA-ID match with an existing tracker. -- [`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) — +- [`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) — reconciles a security issue with its GitHub discussion, its `` mail thread, and any fixing PRs; proposes label, milestone, field, and draft-email updates; and prompts the user to confirm each change before applying it. Points the user at - [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) when a CVE is + [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) when a CVE is needed. **At the end of every run** it also invokes [`generate-cve-json`](tools/vulnogram/generate-cve-json/SKILL.md) with `--attach` to refresh the CVE JSON attachment on the tracking issue (auto- @@ -1090,7 +1090,7 @@ Currently available: in the *PR with the fix* body field), so the attached JSON stays in lock-step with the issue body. Skipped only when no CVE has been allocated yet, or when the issue has been closed as invalid / not-CVE-worthy / duplicate. -- [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) — walks the +- [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) — walks the user through allocating a CVE via the adopting project's CVE-tool allocation form (for Airflow, ASF Vulnogram at ; see @@ -1111,11 +1111,11 @@ Currently available: a collapsed status-change comment, regenerates the CVE JSON attachment in the body via `generate-cve-json --attach`, and (when relevant) drafts a reporter status update on the original mail thread. **Always - hands off to `security-sync-issues`** at the end so the allocation- + hands off to `security-issue-sync`** at the end so the allocation- triggered changes are reconciled with the milestone, assignee, fix-PR state, and reporter-thread state in one continuous flow. -- [`security-fix-issue`](.claude/skills/security-fix-issue/SKILL.md) — runs - `security-sync-issues` first, then analyses the issue discussion to decide +- [`security-issue-fix`](.claude/skills/security-issue-fix/SKILL.md) — runs + `security-issue-sync` first, then analyses the issue discussion to decide whether the reported problem is easily fixable (clear consensus, small scope, known location). If it is, proposes an implementation plan, writes the change in the user's local `` clone (path from @@ -1165,4 +1165,4 @@ When adding a new skill: - [`tools/github/`](tools/github/) — GitHub tool adapter: `tool.md` (overview), `operations.md` (`gh` CLI / API catalogue), `issue-template.md` (body-field schema), `labels.md` (lifecycle-label taxonomy), `project-board.md` (Projects V2 GraphQL). - [`tools/gmail/`](tools/gmail/) — Gmail tool adapter: `tool.md` (overview), `operations.md` (MCP catalogue + no-update limitation), `threading.md` (prefer-`threadId`-else-subject-fallback rule), `asf-relay.md` (ASF-security-relay drafting), `search-queries.md` (query templates), `ponymail-archive.md` (ASF PonyMail URL construction). - [`tools/vulnogram/`](tools/vulnogram/) — Vulnogram (ASF CVE tool) adapter: `tool.md` (overview), `allocation.md` (PMC-gated allocation flow), `record.md` (record URLs + `#source` paste + `DRAFT`/`REVIEW`/`PUBLIC` state machine + reviewer-comment signal), `generate-cve-json/` (CVE-5.x JSON generator — Python project). -- [`tools/cve-org/`](tools/cve-org/) — public CVE registry adapter: `tool.md` covers the MITRE CVE Services API v2 `check-published` recipe, used by `security-sync-issues` to verify that a closed tracker's CVE has propagated from the CNA tool to cve.org before sending the reporter the final *"CVE is live"* email. +- [`tools/cve-org/`](tools/cve-org/) — public CVE registry adapter: `tool.md` covers the MITRE CVE Services API v2 `check-published` recipe, used by `security-issue-sync` to verify that a closed tracker's CVE has propagated from the CNA tool to cve.org before sending the reporter the final *"CVE is live"* email. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 37bbf8cf..9e152692 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -90,13 +90,13 @@ four — no hard-coded project assumptions anywhere. │ ├── .claude/ │ └── skills/ # Agent workflows (invoked via the Skill tool) -│ ├── security-import-issues/SKILL.md -│ ├── security-import-issue-from-pr/SKILL.md -│ ├── security-sync-issues/SKILL.md -│ ├── security-allocate-cve/SKILL.md -│ ├── security-fix-issue/SKILL.md -│ ├── security-deduplicate-issues/SKILL.md -│ └── security-invalidate-issue/SKILL.md +│ ├── security-issue-import/SKILL.md +│ ├── security-issue-import-from-pr/SKILL.md +│ ├── security-issue-sync/SKILL.md +│ ├── security-cve-allocate/SKILL.md +│ ├── security-issue-fix/SKILL.md +│ ├── security-issue-deduplicate/SKILL.md +│ └── security-issue-invalidate/SKILL.md │ ├── config/ # Runtime configuration layer │ ├── README.md # Configuration tutorial + placeholder rule @@ -268,8 +268,8 @@ uv run ruff format # auto-format (check-only in CI) uv run mypy # type-check ``` -The package is invoked by the [`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) -and [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) skills via +The package is invoked by the [`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) +and [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) skills via `uv run --project tools/vulnogram/generate-cve-json generate-cve-json --attach` from the repo root — that is the canonical invocation any new behaviour has to stay compatible with. diff --git a/README.md b/README.md index d656da62..85af7ed6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ - [3. GitHub connection (GitHub MCP / `gh` CLI)](#3-github-connection-github-mcp--gh-cli) - [4. PMC membership (only for CVE allocation)](#4-pmc-membership-only-for-cve-allocation) - [5. Browser (for the human-click steps)](#5-browser-for-the-human-click-steps) - - [6. Local `` clone (only for `security-fix-issue`)](#6-local-upstream-clone-only-for-security-fix-issue) + - [6. Local `` clone (only for `security-issue-fix`)](#6-local-upstream-clone-only-for-security-issue-fix) - [7. `uv` (for `generate-cve-json`)](#7-uv-for-generate-cve-json) - [Shared conventions](#shared-conventions) - [Keeping the reporter informed](#keeping-the-reporter-informed) @@ -148,7 +148,7 @@ section — a browser and your `` collaborator access are enough. If you plan to **run any of the agent skills** (`import`, `sync`, -`security-allocate-cve`, `fix`, `generate-cve-json`, `deduplicate`) — typically +`security-cve-allocate`, `fix`, `generate-cve-json`, `deduplicate`) — typically as a rotational triager, remediation developer, or release manager — check the following setup **before** invoking a skill. Each skill also runs a short Step 0 pre-flight against the same list and stops with a @@ -177,7 +177,7 @@ configs. ### 2. Email connection (Gmail MCP, today) -The import, sync, and security-allocate-cve skills **read the security-list +The import, sync, and security-cve-allocate skills **read the security-list mail thread** associated with each tracker and draft replies on that thread. Today this goes through the [Claude Gmail MCP](https://docs.anthropic.com/en/docs/build-with-claude/mcp) @@ -196,8 +196,8 @@ without connecting their personal Gmail — authenticating directly against ASF credentials (and, eventually, the ASF's new MFA) will be sufficient. Until then, Gmail MCP is the way. -**Without this connection:** `security-import-issues` cannot find new -reports, `security-sync-issues` cannot reconcile status with the mail +**Without this connection:** `security-issue-import` cannot find new +reports, `security-issue-sync` cannot reconcile status with the mail thread, and no skill can draft replies to reporters. The skills will refuse to start and tell you to configure the MCP first. @@ -212,7 +212,7 @@ CLI directly for some calls. What the skills need: security-team roster is maintained per-project; for the active project see [`/release-trains.md`](/release-trains.md#security-team-roster). -- For `security-fix-issue`: a fork of `` on your GitHub +- For `security-issue-fix`: a fork of `` on your GitHub account (the skill pushes a branch there before opening the PR via `gh pr create --web`). @@ -220,7 +220,7 @@ CLI directly for some calls. What the skills need: The adopting project's CVE-tool allocation form is **PMC-gated** on the server side — only the project's PMC members can submit a CVE -allocation. Non-PMC triagers can still run `security-allocate-cve`; the +allocation. Non-PMC triagers can still run `security-cve-allocate`; the skill detects this up front (it asks *"are you a PMC member of ``?"*) and produces a relay message for a PMC member to click through instead. For Airflow the concrete tool is ASF's @@ -239,7 +239,7 @@ paste, the `gh pr create --web` compose view. The skills prepare the URL and the exact text to paste and hand it off to the browser; they do not try to automate those clicks. -### 6. Local `` clone (only for `security-fix-issue`) +### 6. Local `` clone (only for `security-issue-fix`) The fix skill writes the change in your local clone, runs local checks and tests, pushes a branch to your fork, and opens a PR via @@ -332,12 +332,12 @@ and framework-lifecycle housekeeping. | Skill | Purpose | |---|---| -| [`setup-secure-config`](.claude/skills/setup-secure-config/SKILL.md) | First-time install of the secure agent setup. | -| [`setup-verify-secure-config`](.claude/skills/setup-verify-secure-config/SKILL.md) | Verify the secure setup landed correctly. | -| [`setup-update-secure-config`](.claude/skills/setup-update-secure-config/SKILL.md) | Surface drift between the installed setup and the framework's latest. | -| [`setup-upgrade-steward`](.claude/skills/setup-upgrade-steward/SKILL.md) | Pull the framework checkout to latest `origin/main`. | -| [`setup-verify-steward`](.claude/skills/setup-verify-steward/SKILL.md) | Verify the framework is integrated correctly into an adopter tracker. | -| [`setup-sync-shared-config`](.claude/skills/setup-sync-shared-config/SKILL.md) | Commit + push the user's shared Claude config to its sync repo. | +| [`setup-isolated-setup-install`](.claude/skills/setup-isolated-setup-install/SKILL.md) | First-time install of the secure agent setup. | +| [`setup-isolated-setup-verify`](.claude/skills/setup-isolated-setup-verify/SKILL.md) | Verify the secure setup landed correctly. | +| [`setup-isolated-setup-update`](.claude/skills/setup-isolated-setup-update/SKILL.md) | Surface drift between the installed setup and the framework's latest. | +| [`setup-steward-upgrade`](.claude/skills/setup-steward-upgrade/SKILL.md) | Pull the framework checkout to latest `origin/main`. | +| [`setup-steward-verify`](.claude/skills/setup-steward-verify/SKILL.md) | Verify the framework is integrated correctly into an adopter tracker. | +| [`setup-shared-config-sync`](.claude/skills/setup-shared-config-sync/SKILL.md) | Commit + push the user's shared Claude config to its sync repo. | ### Security workflow @@ -348,14 +348,14 @@ cross-skill flow as a diagram. | Skill | Purpose | |---|---| -| [`security-import-issues`](.claude/skills/security-import-issues/SKILL.md) | Import new reports from `` into ``. | -| [`security-import-issue-from-pr`](.claude/skills/security-import-issue-from-pr/SKILL.md) | Open a tracker for a security-relevant fix opened as a public PR. | -| [`security-import-issues-from-md`](.claude/skills/security-import-issues-from-md/SKILL.md) | Bulk-import findings from a markdown report. | -| [`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) | Reconcile a tracker against its mail thread, fix PR, release train, and archives. | -| [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) | Allocate a CVE for a tracker (Vulnogram URL + paste-ready JSON). | -| [`security-fix-issue`](.claude/skills/security-fix-issue/SKILL.md) | Implement the fix as a public PR in ``. | -| [`security-deduplicate-issues`](.claude/skills/security-deduplicate-issues/SKILL.md) | Merge two trackers describing the same root-cause vulnerability. | -| [`security-invalidate-issue`](.claude/skills/security-invalidate-issue/SKILL.md) | Close a tracker as invalid with a polite-but-firm reporter reply. | +| [`security-issue-import`](.claude/skills/security-issue-import/SKILL.md) | Import new reports from `` into ``. | +| [`security-issue-import-from-pr`](.claude/skills/security-issue-import-from-pr/SKILL.md) | Open a tracker for a security-relevant fix opened as a public PR. | +| [`security-issue-import-from-md`](.claude/skills/security-issue-import-from-md/SKILL.md) | Bulk-import findings from a markdown report. | +| [`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) | Reconcile a tracker against its mail thread, fix PR, release train, and archives. | +| [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) | Allocate a CVE for a tracker (Vulnogram URL + paste-ready JSON). | +| [`security-issue-fix`](.claude/skills/security-issue-fix/SKILL.md) | Implement the fix as a public PR in ``. | +| [`security-issue-deduplicate`](.claude/skills/security-issue-deduplicate/SKILL.md) | Merge two trackers describing the same root-cause vulnerability. | +| [`security-issue-invalidate`](.claude/skills/security-issue-invalidate/SKILL.md) | Close a tracker as invalid with a polite-but-firm reporter reply. | ### PR triage and review @@ -366,19 +366,19 @@ contributor PR queue can reuse the same playbook. | Skill | Purpose | |---|---| -| [`pr-triage`](.claude/skills/pr-triage/SKILL.md) | Sweep open PRs, classify against the project's quality criteria, propose a disposition (draft / comment / close / rebase / rerun / mark ready / ping), execute on confirmation. | -| [`pr-stats`](.claude/skills/pr-stats/SKILL.md) | Read-only summary tables of the open PR backlog grouped by area label — measure where queue pressure sits. | -| [`pr-maintainer-review`](.claude/skills/pr-maintainer-review/SKILL.md) | Walk a maintainer through deep code review, one PR at a time. Reads the diff, applies the project's review criteria, drafts an `approve` / `request-changes` / `comment` review with inline comments, posts on confirmation. | +| [`pr-management-triage`](.claude/skills/pr-management-triage/SKILL.md) | Sweep open PRs, classify against the project's quality criteria, propose a disposition (draft / comment / close / rebase / rerun / mark ready / ping), execute on confirmation. | +| [`pr-management-stats`](.claude/skills/pr-management-stats/SKILL.md) | Read-only summary tables of the open PR backlog grouped by area label — measure where queue pressure sits. | +| [`pr-management-code-review`](.claude/skills/pr-management-code-review/SKILL.md) | Walk a maintainer through deep code review, one PR at a time. Reads the diff, applies the project's review criteria, drafts an `approve` / `request-changes` / `comment` review with inline comments, posts on confirmation. | Project-specific content (committers team handle, area-label prefix, CI-check → doc URL map, comment-template wording, review- criteria source files) lives in the adopter's `/` under the per-skill scaffolds in -[`projects/_template/pr-triage-config.md`](projects/_template/pr-triage-config.md), -[`projects/_template/pr-triage-comment-templates.md`](projects/_template/pr-triage-comment-templates.md), -[`projects/_template/pr-triage-ci-check-map.md`](projects/_template/pr-triage-ci-check-map.md), +[`projects/_template/pr-management-config.md`](projects/_template/pr-management-config.md), +[`projects/_template/pr-management-triage-comment-templates.md`](projects/_template/pr-management-triage-comment-templates.md), +[`projects/_template/pr-management-triage-ci-check-map.md`](projects/_template/pr-management-triage-ci-check-map.md), and -[`projects/_template/pr-maintainer-review-criteria.md`](projects/_template/pr-maintainer-review-criteria.md). +[`projects/_template/pr-management-code-review-criteria.md`](projects/_template/pr-management-code-review-criteria.md). The framework currently ships with airflow-flavored defaults inline in the supporting files of each skill — non-airflow adopters override by forking the relevant supporting file into @@ -401,19 +401,19 @@ the tracker. A typical triage sweep runs three skills in order: 1. **`import new reports`** — - [`security-import-issues`](.claude/skills/security-import-issues/SKILL.md) + [`security-issue-import`](.claude/skills/security-issue-import/SKILL.md) scans `` for threads not yet imported, classifies each candidate (real report vs. automated-scan / consolidated / media / spam), and proposes a tracker per valid report plus a receipt-of-confirmation Gmail draft. See [Step 2](#step-2--import-the-report). 2. **`sync all`** — - [`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) + [`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) reconciles every open tracker against its mail thread, the fix PR, the release train, and the users@ archive. Proposes label / milestone / assignee / body changes in one pass. 3. **`allocate CVE for issue #N`** — - [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) when a report has + [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) when a report has been assessed as valid. See [Step 6](#step-6--allocate-the-cve). Nothing is applied without an explicit confirmation — each skill is a @@ -430,7 +430,7 @@ When the report is confirmed valid, apply exactly one scope label from the project's scope set (declared in [`/scope-labels.md`](/scope-labels.md)). If a report affects more than one scope, split into per-scope trackers -before allocation — the `security-sync-issues` skill surfaces this as +before allocation — the `security-issue-sync` skill surfaces this as a blocker. See [Step 5](#step-5--land-the-validinvalid-consensus). @@ -439,37 +439,37 @@ If discussion stalls for about 30 days, escalate to a broader audience per ### Allocating the CVE -Use [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md). The skill asks up +Use [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md). The skill asks up front whether you are on the PMC; if not, it reshapes the recipe into an ``@``-mention relay message you forward to a PMC member on the tracker or on the `` thread. Once the allocated `CVE-YYYY-NNNNN` is pasted back, the skill wires it into the tracker in one pass (the *CVE tool link* body field, the `cve allocated` label, a status-change comment, a -refreshed CVE-JSON attachment) and hands off to `security-sync-issues` to +refreshed CVE-JSON attachment) and hands off to `security-issue-sync` to reconcile the rest of the tracker. See [Step 6](#step-6--allocate-the-cve) for the full detail. ### Tools you use most -- [`security-import-issues`](.claude/skills/security-import-issues/SKILL.md) — +- [`security-issue-import`](.claude/skills/security-issue-import/SKILL.md) — *"import new reports"* at the start of each triage sweep. The entry point into the process for `` reports. -- [`security-import-issue-from-pr`](.claude/skills/security-import-issue-from-pr/SKILL.md) — +- [`security-issue-import-from-pr`](.claude/skills/security-issue-import-from-pr/SKILL.md) — *"import a tracker from PR "* when a security-relevant fix landed publicly without going through `` and the team has agreed it warrants a CVE. Lands directly in the `Assessed` column. -- [`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) — +- [`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) — *"sync "* or *"sync all"*. Surfaces stalled issues, missing fields, credit replies, and scope-split requirements in one combined proposal. -- [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) — *"allocate a CVE +- [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) — *"allocate a CVE for "*. - [`generate-cve-json`](tools/vulnogram/generate-cve-json/SKILL.md) — to refresh the paste-ready JSON embedded in the issue body on demand. -- [`security-deduplicate-issues`](.claude/skills/security-deduplicate-issues/SKILL.md) — +- [`security-issue-deduplicate`](.claude/skills/security-issue-deduplicate/SKILL.md) — when two trackers describe the same root-cause bug discovered independently. -- [`security-invalidate-issue`](.claude/skills/security-invalidate-issue/SKILL.md) — +- [`security-issue-invalidate`](.claude/skills/security-issue-invalidate/SKILL.md) — *"close NN as invalid"* once Step 5 lands a consensus-invalid decision. Applies the `invalid` label, archives the project-board item, and (for ``-imported trackers) drafts a reply @@ -492,11 +492,11 @@ ownership. See [Step 7](#step-7--self-assign-and-implement-the-fix). ### Attempting an automated fix Before writing the fix by hand, consider letting the -[`security-fix-issue`](.claude/skills/security-fix-issue/SKILL.md) skill try +[`security-issue-fix`](.claude/skills/security-issue-fix/SKILL.md) skill try it first. Invoked as *"try to fix issue #N"* (or *"draft a PR for #N"*), the skill: -- runs `security-sync-issues` first to make sure the tracker's state is +- runs `security-issue-sync` first to make sure the tracker's state is current; - reads the full tracker discussion and the linked `security@` mail thread and decides whether the issue is *easily fixable* — clear @@ -515,7 +515,7 @@ skill: and similar leakage before being written or pushed; - updates the `` tracking issue with the new PR link and applies the `pr created` label, handing back off to - `security-sync-issues`. + `security-issue-sync`. The skill refuses to proceed in cases where a human decision still needs to happen: reports that are still being assessed, reports not @@ -552,7 +552,7 @@ tests manually before asking for review. Once approved, re-open the PR in ### Handoff to the release manager -Once the `` PR merges, `security-sync-issues` moves the tracker +Once the `` PR merges, `security-issue-sync` moves the tracker from `pr created` to `pr merged` and sets the milestone of the release the fix will ship in. The tracker then waits for the release train. When the release ships, sync swaps `pr merged` → `fix released` and the tracker @@ -561,12 +561,12 @@ becomes the release manager's responsibility. See ### Tools you use most -- [`security-fix-issue`](.claude/skills/security-fix-issue/SKILL.md) — +- [`security-issue-fix`](.claude/skills/security-issue-fix/SKILL.md) — *"try to fix issue #N"*. Proposes a plan, writes the code, runs local tests, and opens a `--web` PR with a scrubbed title/body. See [Attempting an automated fix](#attempting-an-automated-fix) above for the full flow and the cases where the skill refuses to proceed. -- [`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) — to +- [`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) — to keep the tracker's labels, milestone, and assignee aligned with the PR state as it moves through review and merge. @@ -574,7 +574,7 @@ becomes the release manager's responsibility. See You own the tracker from the moment the fix actually ships (`fix released`) to a closed tracking issue with a PUBLISHED CVE record. The hand-off from -the remediation developer is automatic: `security-sync-issues` detects the +the remediation developer is automatic: `security-issue-sync` detects the milestone version on PyPI / the Helm registry, swaps `pr merged` → `fix released`, and assigns the advisory-send to you. @@ -596,7 +596,7 @@ issue yet** — see [Step 13](#step-13--send-the-advisory). ### Capturing the public archive URL This is a handoff the sync skill handles for you: once the advisory has -been archived on the users@ list, the next `security-sync-issues` run finds +been archived on the users@ list, the next `security-issue-sync` run finds the URL, populates the *Public advisory URL* body field, regenerates the CVE JSON attachment, and moves the label to `announced`. See [Step 14](#step-14--capture-the-public-advisory-url). @@ -622,7 +622,7 @@ security team to push the information to `cve.org`. See ### Tools you use most -- [`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) — +- [`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) — *"sync announced"* at the start of each release window, to see the `announced` backlog needing a Vulnogram push. Also *"sync CVE-YYYY-NNNN"* to drill into one specific CVE before sending the @@ -703,7 +703,7 @@ project list). ### Step 2 — Import the report -[`security-import-issues`](.claude/skills/security-import-issues/SKILL.md) +[`security-issue-import`](.claude/skills/security-issue-import/SKILL.md) scans `` for un-imported threads, classifies each candidate (real / automated-scan / consolidated / spam), extracts the issue-template fields from the root message, and proposes one tracker @@ -718,14 +718,14 @@ and does **not** create a tracker — invalid noise never enters the board. **Alternate entry — fix already opened as a public PR.** Use -[`security-import-issue-from-pr`](.claude/skills/security-import-issue-from-pr/SKILL.md). +[`security-issue-import-from-pr`](.claude/skills/security-issue-import-from-pr/SKILL.md). The tracker lands directly in the `Assessed` column with the scope label applied (validity already decided informally), so Step 5 is -skipped and the tracker is ready for `security-allocate-cve` +skipped and the tracker is ready for `security-cve-allocate` immediately. **Alternate entry — bulk import from markdown.** Use -[`security-import-issues-from-md`](.claude/skills/security-import-issues-from-md/SKILL.md) +[`security-issue-import-from-md`](.claude/skills/security-issue-import-from-md/SKILL.md) when triaging the output of an AI security review or third-party scanner. Each finding becomes one tracker. @@ -764,7 +764,7 @@ with the action label `Sync (Step 4 escalation)`. If valid, apply exactly one scope label from [`/scope-labels.md`](/scope-labels.md); remove `needs triage`. If invalid, -[`security-invalidate-issue`](.claude/skills/security-invalidate-issue/SKILL.md) +[`security-issue-invalidate`](.claude/skills/security-issue-invalidate/SKILL.md) labels `invalid`, posts a closing comment, archives the board item, and (for ``-imported trackers) drafts a polite-but-firm reporter reply. If consensus cannot be reached, follow @@ -772,7 +772,7 @@ reporter reply. If consensus cannot be reached, follow on ``. If a candidate duplicate is detected, -[`security-deduplicate-issues`](.claude/skills/security-deduplicate-issues/SKILL.md) +[`security-issue-deduplicate`](.claude/skills/security-issue-deduplicate/SKILL.md) merges two trackers in place — preserving every reporter's credit, every mailing-list thread reference, and every independent attack-vector description. The kept issue's body is updated, the @@ -781,7 +781,7 @@ attachment is regenerated so both finders land in `credits[]`. ### Step 6 — Allocate the CVE -[`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) +[`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) opens the project's CVE allocation tool (for Airflow, ASF Vulnogram at ; in general see [`/project.md → CVE tooling`](/project.md#cve-tooling)), @@ -791,14 +791,14 @@ and — if the triager isn't on the PMC — builds an `@`-mention relay message for a PMC member. Once the allocated `CVE-YYYY-NNNNN` is pasted back, the skill wires it into the tracker (CVE tool link body field, `cve allocated` label, status-change comment, refreshed -CVE-JSON attachment) and hands off to `security-sync-issues` to +CVE-JSON attachment) and hands off to `security-issue-sync` to reconcile the rest. ### Step 7 — Self-assign and implement the fix A security team member self-assigns and implements the fix. Optional automation: -[`security-fix-issue`](.claude/skills/security-fix-issue/SKILL.md) +[`security-issue-fix`](.claude/skills/security-issue-fix/SKILL.md) proposes an implementation plan, writes the change in your local `` clone, runs local tests, and opens a public PR via `gh pr create --web` with a scrubbed title + body. Every public @@ -850,7 +850,7 @@ patches) or weeks (provider waves on a fixed cadence). When the release containing the fix ships to users (PyPI / Helm registry / equivalent), -[`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) +[`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) detects the release version on the next run and proposes the `pr merged` → `fix released` swap, which is the hand-off cue from remediation developer to release manager. The same pass proposes @@ -881,7 +881,7 @@ issue stays open** at this point — it closes only at Step 15. ### Step 14 — Capture the public advisory URL Once the announcement is archived on the users@ list, the next -`security-sync-issues` run finds the URL, populates the *Public +`security-issue-sync` run finds the URL, populates the *Public advisory URL* body field (a dedicated field on the issue template — never reuse the *"Security mailing list thread"* field), regenerates the CVE JSON attachment (now carrying a `vendor-advisory` reference), @@ -900,7 +900,7 @@ The release manager opens the project's CVE tool's `#source` view at latest CVE JSON attachment from the tracker (the one regenerated in Step 14), pastes it into the form, saves, and moves the record from READY to PUBLIC — propagating to [`cve.org`](https://cve.org). Then -closes the tracker (no label updates). `security-sync-issues` +closes the tracker (no label updates). `security-issue-sync` follows the close with an `archiveProjectV2Item` mutation so the closed tracker leaves the active board (see [`tools/github/project-board.md` — *Archive a board item*](tools/github/project-board.md#archive-a-board-item--terminal-state-cleanup)). @@ -929,8 +929,8 @@ the issue forward. Closing dispositions (`invalid`, `not CVE worthy`, ```mermaid flowchart TD - A([report on project security list]) -->|step 2: security-import-issues| B[needs triage] - A2([security-relevant fix in public PR]) -->|step 2 alt: security-import-issue-from-pr| C + A([report on project security list]) -->|step 2: security-issue-import| B[needs triage] + A2([security-relevant fix in public PR]) -->|step 2 alt: security-issue-import-from-pr| C B -->|step 5: consensus invalid| X1([invalid / not CVE worthy / duplicate / wontfix]) B -->|step 5: consensus valid| C["scope label
(project-specific — see
projects/<PROJECT>/scope-labels.md)"] C -->|step 6: CVE reserved by PMC member| D[cve allocated] @@ -970,7 +970,7 @@ labels the adopting project defines. | --- | --- | --- | --- | | `needs triage` | Freshly filed; assessment not yet started. | 1 | 5 | | `` | Scope of the vulnerability. Exactly one project-specific scope label is set. | 5 | never (sticks for the lifetime of the issue) | -| `cve allocated` | A CVE has been reserved for the issue. Allocation itself is PMC-gated (only the adopting project's PMC members can submit the CVE-tool allocation form); a non-PMC triager relays a request to a PMC member via the [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) skill. | 6 | never | +| `cve allocated` | A CVE has been reserved for the issue. Allocation itself is PMC-gated (only the adopting project's PMC members can submit the CVE-tool allocation form); a non-PMC triager relays a request to a PMC member via the [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) skill. | 6 | never | | `pr created` | A public fix PR has been opened on `` but has not yet merged. | 10 | 11 (replaced by `pr merged`) | | `pr merged` | The fix PR has merged into ``; no release with the fix has shipped yet. | 11 | 12 (replaced by `fix released` when the release ships) | | `fix released` | A release containing the fix has shipped to users; advisory has not been sent yet. | 12 | 13 (replaced by `announced - emails sent`) | @@ -978,7 +978,7 @@ labels the adopting project defines. | `announced` | The public advisory URL has been captured in the tracking issue's *Public advisory URL* body field and the attached CVE JSON has been regenerated so its `references[]` now carries the `vendor-advisory` URL. The tracking issue is waiting for the release manager to copy the CVE JSON into the project's CVE tool, move the record to PUBLIC, and close the issue (Step 15). No label changes at close — the issue closes with `announced` still set. | 14 | never (stays on the issue after closing) | | `wontfix` / `invalid` / `not CVE worthy` / `duplicate` | Closing dispositions for reports that are not valid or not CVE-worthy. | 5 / 6 | — | -The [`security-sync-issues`](.claude/skills/security-sync-issues/SKILL.md) +The [`security-issue-sync`](.claude/skills/security-issue-sync/SKILL.md) skill keeps these labels honest: on every run it detects the current state of the issue, the fix PR, and the release train, and proposes the label transitions the process requires. @@ -1025,7 +1025,7 @@ repo: ``` The framework's -[`setup-verify-steward`](.claude/skills/setup-verify-steward/SKILL.md) +[`setup-steward-verify`](.claude/skills/setup-steward-verify/SKILL.md) skill checks each of these and reports `✓ done / ✗ missing / ⚠ partial` for the adopter integration — run it after step 3 to confirm the install landed. @@ -1058,10 +1058,10 @@ four scaffold files for project-specific knobs: | File | Used by | |---|---| -| [`pr-triage-config.md`](projects/_template/pr-triage-config.md) | `pr-triage`, `pr-stats` | -| [`pr-triage-comment-templates.md`](projects/_template/pr-triage-comment-templates.md) | `pr-triage` | -| [`pr-triage-ci-check-map.md`](projects/_template/pr-triage-ci-check-map.md) | `pr-triage` | -| [`pr-maintainer-review-criteria.md`](projects/_template/pr-maintainer-review-criteria.md) | `pr-maintainer-review` | +| [`pr-management-config.md`](projects/_template/pr-management-config.md) | `pr-management-triage`, `pr-management-stats` | +| [`pr-management-triage-comment-templates.md`](projects/_template/pr-management-triage-comment-templates.md) | `pr-management-triage` | +| [`pr-management-triage-ci-check-map.md`](projects/_template/pr-management-triage-ci-check-map.md) | `pr-management-triage` | +| [`pr-management-code-review-criteria.md`](projects/_template/pr-management-code-review-criteria.md) | `pr-management-code-review` | Each PR-skill's `SKILL.md` carries an `## Adopter configuration` section that documents which of these files it reads. The framework @@ -1104,7 +1104,7 @@ chmod +x .git/hooks/post-merge ``` The framework's -[`setup-upgrade-steward`](.claude/skills/setup-upgrade-steward/SKILL.md) +[`setup-steward-upgrade`](.claude/skills/setup-steward-upgrade/SKILL.md) skill upgrades the framework checkout itself; if the user is consuming the framework as a tracker submodule, the skill reminds them to follow up with submodule update on the parent tracker. diff --git a/how-to-fix-a-security-issue.md b/how-to-fix-a-security-issue.md index 3fb77c45..e04d041d 100644 --- a/how-to-fix-a-security-issue.md +++ b/how-to-fix-a-security-issue.md @@ -33,7 +33,7 @@ page is the two-minute summary. 2. **Triage.** A rotating triager imports new reports into the private `` repository (see the - [`security-import-issues`](.claude/skills/security-import-issues/SKILL.md) + [`security-issue-import`](.claude/skills/security-issue-import/SKILL.md) skill), classifies each candidate, and drafts a receipt-of-confirmation reply to the reporter. The team then discusses CVE-worthiness in the issue comments and — once the @@ -43,7 +43,7 @@ page is the two-minute summary. For the rarer case where a security-relevant fix lands as a public PR on `` without ever hitting ``, the triager uses - [`security-import-issue-from-pr`](.claude/skills/security-import-issue-from-pr/SKILL.md) + [`security-issue-import-from-pr`](.claude/skills/security-issue-import-from-pr/SKILL.md) instead. The skill creates the tracker directly with a scope label and the `Assessed` board column — the deliberate import implies the validity assessment has already happened informally, @@ -52,7 +52,7 @@ page is the two-minute summary. When the team's discussion lands a *consensus-invalid* decision, the triager applies that decision via the - [`security-invalidate-issue`](.claude/skills/security-invalidate-issue/SKILL.md) + [`security-issue-invalidate`](.claude/skills/security-issue-invalidate/SKILL.md) skill: it adds the `invalid` label, posts a short closing comment, archives the project-board item, and — when the tracker has an inbound `` thread — drafts a @@ -70,13 +70,13 @@ page is the two-minute summary. A PMC member of the adopting project allocates a CVE through the project's CVE tool (for Airflow, ASF Vulnogram). The allocation is PMC-gated; non-PMC triagers use the - [`security-allocate-cve`](.claude/skills/security-allocate-cve/SKILL.md) skill to + [`security-cve-allocate`](.claude/skills/security-cve-allocate/SKILL.md) skill to produce a relay message for a PMC member to click through. 4. **Remediation.** A security-team member writes the fix in the public `` repository (see the - [`security-fix-issue`](.claude/skills/security-fix-issue/SKILL.md) + [`security-issue-fix`](.claude/skills/security-issue-fix/SKILL.md) skill, which can draft the PR automatically). The public PR is scrubbed of CVE references, tracker-repo references, and any *"security fix"* signal — per the confidentiality rules in diff --git a/new-members-onboarding.md b/new-members-onboarding.md index d8ea194d..bbab155e 100644 --- a/new-members-onboarding.md +++ b/new-members-onboarding.md @@ -150,7 +150,7 @@ perspective: codebase. - **Release manager** is usually inherited rather than volunteered for: when you cut a release that contains a security fix, - `security-sync-issues` hands those trackers to you with + `security-issue-sync` hands those trackers to you with `fix released` and you own them through the advisory + Vulnogram steps. @@ -188,7 +188,7 @@ There is also a fourth command for anyone willing to take on a remediation-developer turn: - **`try to fix issue #N`** — - [`security-fix-issue`](.claude/skills/security-fix-issue/SKILL.md) + [`security-issue-fix`](.claude/skills/security-issue-fix/SKILL.md) attempts to land the fix for a triaged tracker in one go. It runs a pre-fix sync, reads the discussion on the tracker to build a fix plan, shows you the plan, and — only after you confirm — writes the diff --git a/projects/_template/README.md b/projects/_template/README.md index 47498aad..922e66b4 100644 --- a/projects/_template/README.md +++ b/projects/_template/README.md @@ -73,7 +73,7 @@ the rest. | File | Purpose | |---|---| -| [`title-normalization.md`](title-normalization.md) | Regex cascade the `security-allocate-cve` skill applies to tracker titles before pasting them into the CVE-tool allocation form. | +| [`title-normalization.md`](title-normalization.md) | Regex cascade the `security-cve-allocate` skill applies to tracker titles before pasting them into the CVE-tool allocation form. | ### Remediation workflow @@ -91,23 +91,23 @@ the rest. ### PR triage and review These files configure the -[`pr-triage`](../../.claude/skills/pr-triage/SKILL.md), -[`pr-stats`](../../.claude/skills/pr-stats/SKILL.md), and -[`pr-maintainer-review`](../../.claude/skills/pr-maintainer-review/SKILL.md) +[`pr-management-triage`](../../.claude/skills/pr-management-triage/SKILL.md), +[`pr-management-stats`](../../.claude/skills/pr-management-stats/SKILL.md), and +[`pr-management-code-review`](../../.claude/skills/pr-management-code-review/SKILL.md) skills. Adopters who only use the security skills can delete these four files; adopters running maintainer-side PR-queue management fill them in. | File | Purpose | |---|---| -| [`pr-triage-config.md`](pr-triage-config.md) | Committers team handle, area-label prefix, project-specific labels (`ready for maintainer review`, etc.), grace windows. Used by `pr-triage` and `pr-stats`. | -| [`pr-triage-comment-templates.md`](pr-triage-comment-templates.md) | Comment-body URLs (PR quality criteria, two-stage triage rationale), AI-attribution footer wording, project display name. Used by `pr-triage`. | -| [`pr-triage-ci-check-map.md`](pr-triage-ci-check-map.md) | CI-check name pattern → category name + doc-URL mapping for the violations comment. Used by `pr-triage`. | -| [`pr-maintainer-review-criteria.md`](pr-maintainer-review-criteria.md) | List of project's review-criteria source files (repo-wide AGENTS.md, code-review docs, per-area AGENTS.md), security-model calibration doc, backport-branch pattern, section-anchor URLs. Used by `pr-maintainer-review`. | +| [`pr-management-config.md`](pr-management-config.md) | Committers team handle, area-label prefix, project-specific labels (`ready for maintainer review`, etc.), grace windows. Used by `pr-management-triage` and `pr-management-stats`. | +| [`pr-management-triage-comment-templates.md`](pr-management-triage-comment-templates.md) | Comment-body URLs (PR quality criteria, two-stage triage rationale), AI-attribution footer wording, project display name. Used by `pr-management-triage`. | +| [`pr-management-triage-ci-check-map.md`](pr-management-triage-ci-check-map.md) | CI-check name pattern → category name + doc-URL mapping for the violations comment. Used by `pr-management-triage`. | +| [`pr-management-code-review-criteria.md`](pr-management-code-review-criteria.md) | List of project's review-criteria source files (repo-wide AGENTS.md, code-review docs, per-area AGENTS.md), security-model calibration doc, backport-branch pattern, section-anchor URLs. Used by `pr-management-code-review`. | > The framework currently ships with airflow-flavoured defaults > inline in the supporting files of each PR-skill (e.g. -> [`pr-triage/comment-templates.md`](../../.claude/skills/pr-triage/comment-templates.md) +> [`pr-management-triage/comment-templates.md`](../../.claude/skills/pr-management-triage/comment-templates.md) > embeds airflow's PR-quality-criteria URL). A follow-up PR will > complete the extraction so the skills read exclusively from > `/`. Until then, non-airflow adopters override by @@ -127,15 +127,15 @@ skills): - [ ] `scope-labels.md` lists at least one scope label (exactly-one-of rule). - [ ] `security-model.md` points at the project's authoritative Security-Model URL. - [ ] `release-trains.md` has at least one current release branch + its RM. -- [ ] `canned-responses.md` has at least the *"Confirmation of receiving the report"* template filled in (the `security-import-issues` skill sends this verbatim). +- [ ] `canned-responses.md` has at least the *"Confirmation of receiving the report"* template filled in (the `security-issue-import` skill sends this verbatim). **PR triage and review** (delete this group if not using the `pr-*` skills): -- [ ] `pr-triage-config.md` — committers team handle and area-label prefix filled in. -- [ ] `pr-triage-comment-templates.md` — ``, ``, and `` filled in. -- [ ] `pr-triage-ci-check-map.md` — at least one CI-check pattern row filled in (or the catch-all row pointing at the project's static-checks doc). -- [ ] `pr-maintainer-review-criteria.md` — at least one repo-wide review-criteria source file declared. +- [ ] `pr-management-config.md` — committers team handle and area-label prefix filled in. +- [ ] `pr-management-triage-comment-templates.md` — ``, ``, and `` filled in. +- [ ] `pr-management-triage-ci-check-map.md` — at least one CI-check pattern row filled in (or the catch-all row pointing at the project's static-checks doc). +- [ ] `pr-management-code-review-criteria.md` — at least one repo-wide review-criteria source file declared. **Common finishers**: diff --git a/projects/_template/canned-responses.md b/projects/_template/canned-responses.md index feee0854..831a36e8 100644 --- a/projects/_template/canned-responses.md +++ b/projects/_template/canned-responses.md @@ -38,7 +38,7 @@ project's Security Model (see [`security-model.md`](security-model.md)) rather than paraphrasing it. -The [`security-import-issues`](../../.claude/skills/security-import-issues/SKILL.md) +The [`security-issue-import`](../../.claude/skills/security-issue-import/SKILL.md) skill sends the *Confirmation of receiving the report* template verbatim on every new inbound report — that one is **load-bearing** and must exist before the skill is useful. The rest can be filled in @@ -56,7 +56,7 @@ the adopting project's voice. TODO: short confirmation that the report has been received, the security team will assess it, and what the reporter should expect next. Include the credit-preference question. Sent verbatim by -`security-import-issues`. +`security-issue-import`. ### Negative assessment — out of scope per the Security Model @@ -107,12 +107,12 @@ Minimum set (one per lifecycle transition): | Template | Process step | Sent by | |---|---|---| -| CVE allocated | Step 6 | `security-allocate-cve` skill | -| Fix PR opened | Step 10 | `security-fix-issue` / `security-sync-issues` skill | -| Fix PR merged | Step 11 | `security-sync-issues` skill | -| Release shipped (fix released) | Step 12 | `security-sync-issues` skill | -| Advisory sent | Step 13 | Release manager + `security-sync-issues` follow-up | -| CVE published on cve.org | post-Step 15 | `security-sync-issues` skill (recently-closed scan) | +| CVE allocated | Step 6 | `security-cve-allocate` skill | +| Fix PR opened | Step 10 | `security-issue-fix` / `security-issue-sync` skill | +| Fix PR merged | Step 11 | `security-issue-sync` skill | +| Release shipped (fix released) | Step 12 | `security-issue-sync` skill | +| Advisory sent | Step 13 | Release manager + `security-issue-sync` follow-up | +| CVE published on cve.org | post-Step 15 | `security-issue-sync` skill (recently-closed scan) | | Credit correction | Step 16 | Release manager | Each row above corresponds to a section below; flesh out the diff --git a/projects/_template/fix-workflow.md b/projects/_template/fix-workflow.md index adbedfca..ec1f4479 100644 --- a/projects/_template/fix-workflow.md +++ b/projects/_template/fix-workflow.md @@ -18,12 +18,12 @@ # TODO: `` — remediation PR workflow specifics -Project-specific mechanics of how the `security-fix-issue` skill +Project-specific mechanics of how the `security-issue-fix` skill opens a public fix PR on the project's `` repository. Only the bits that are **specific to this project** live here; the generic flow (clone → branch → commit → push → `gh pr create --web`) is described in the -[`security-fix-issue`](../../.claude/skills/security-fix-issue/SKILL.md) +[`security-issue-fix`](../../.claude/skills/security-issue-fix/SKILL.md) skill itself. ## Upstream repository @@ -49,7 +49,7 @@ TODO: list the project's developer toolchain. Example shape: - TODO: package manager, e.g. `uv`, `cargo`, `mvn`. - TODO: any project-specific dev shell or test harness. -The `security-fix-issue` skill assumes a clean clone of `` +The `security-issue-fix` skill assumes a clean clone of `` reachable from the agent's working directory (path from `config/user.md → environment.upstream_clone`), with a remote named for the user's GitHub fork that `gh pr create` can push to. diff --git a/projects/_template/milestones.md b/projects/_template/milestones.md index edbe7a20..6b521d0d 100644 --- a/projects/_template/milestones.md +++ b/projects/_template/milestones.md @@ -17,7 +17,7 @@ The project uses GitHub milestones on its `` repository to pin an issue to the release it ships in. Milestones are the hand-off signal from the remediation developer to the release manager; the -`security-sync-issues` skill creates and assigns them as part of the +`security-issue-sync` skill creates and assigns them as part of the `pr merged` → `fix released` transition. TODO: list every milestone format the project uses, one row per @@ -52,7 +52,7 @@ TODO: ## What the milestone unlocks Once the milestone is set on a `pr merged` tracker, the -`security-sync-issues` skill watches for the release to ship and +`security-issue-sync` skill watches for the release to ship and proposes the `pr merged` → `fix released` label swap, which hands ownership off to the release manager for steps 13–15. See the repo-level [`../../README.md`](../../README.md) for the step-by-step diff --git a/projects/_template/pr-maintainer-review-criteria.md b/projects/_template/pr-management-code-review-criteria.md similarity index 93% rename from projects/_template/pr-maintainer-review-criteria.md rename to projects/_template/pr-management-code-review-criteria.md index 30d860e2..b37beef2 100644 --- a/projects/_template/pr-maintainer-review-criteria.md +++ b/projects/_template/pr-management-code-review-criteria.md @@ -2,7 +2,7 @@ **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* -- [TODO: `` — pr-maintainer-review criteria](#todo-project-name--pr-maintainer-review-criteria) +- [TODO: `` — pr-management-code-review criteria](#todo-project-name--pr-management-code-review-criteria) - [Repo-wide source files](#repo-wide-source-files) - [Per-area source files](#per-area-source-files) - [Security-model calibration](#security-model-calibration) @@ -14,11 +14,11 @@ -# TODO: `` — pr-maintainer-review criteria +# TODO: `` — pr-management-code-review criteria This file is the **navigation map** for the project's review criteria — the source files the -[`pr-maintainer-review`](../../.claude/skills/pr-maintainer-review/SKILL.md) +[`pr-management-code-review`](../../.claude/skills/pr-management-code-review/SKILL.md) skill reads when forming its findings. The framework does not restate the rules; this file points at them. diff --git a/projects/_template/pr-triage-config.md b/projects/_template/pr-management-config.md similarity index 81% rename from projects/_template/pr-triage-config.md rename to projects/_template/pr-management-config.md index 5f2e0b13..15c2f944 100644 --- a/projects/_template/pr-triage-config.md +++ b/projects/_template/pr-management-config.md @@ -2,7 +2,7 @@ **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* -- [TODO: `` — pr-triage configuration](#todo-project-name--pr-triage-configuration) +- [TODO: `` — pr-management-triage configuration](#todo-project-name--pr-management-triage-configuration) - [Identifiers](#identifiers) - [Project-specific labels](#project-specific-labels) - [Grace windows](#grace-windows) @@ -12,10 +12,10 @@ -# TODO: `` — pr-triage configuration +# TODO: `` — pr-management-triage configuration This file is the **per-project configuration** for the -[`pr-triage`](../../.claude/skills/pr-triage/SKILL.md) skill. The +[`pr-management-triage`](../../.claude/skills/pr-management-triage/SKILL.md) skill. The framework's skill code reads it to learn project-specific identifiers (committers team, area-label conventions, project- specific labels) without baking any one project's flavor into the @@ -24,7 +24,7 @@ framework. Grep for `TODO` to see every field still to fill in: ```bash -grep -n TODO /pr-triage-config.md +grep -n TODO /pr-management-config.md ``` ## Identifiers @@ -32,7 +32,7 @@ grep -n TODO /pr-triage-config.md | Key | Value | Used by | |---|---|---| | `committers_team` | TODO: e.g. `apache/foo-committers` | `classify-and-act.md` row F5b — team-mention detection. Used to recognise PR comments that `@`-mention the project's committers as a maintainer-to-maintainer ping. | -| `area_label_prefix` | TODO: e.g. `area:` (default) | `classify-and-act.md`, `pr-stats` — area-label grouping. Set to whatever prefix the project uses on its area/scope labels. | +| `area_label_prefix` | TODO: e.g. `area:` (default) | `classify-and-act.md`, `pr-management-stats` — area-label grouping. Set to whatever prefix the project uses on its area/scope labels. | ## Project-specific labels @@ -43,7 +43,7 @@ and the skill will skip that row of decision-table actions. | Concept | Label | Notes | |---|---|---| -| `ready_for_maintainer_review` | TODO: e.g. `ready for maintainer review` | Applied by the `mark-ready` action; used by `pr-maintainer-review` as a default selector. | +| `ready_for_maintainer_review` | TODO: e.g. `ready for maintainer review` | Applied by the `mark-ready` action; used by `pr-management-code-review` as a default selector. | | `quality_violations_close` | TODO: e.g. `quality violations - closed` | Applied when a PR is closed for failing the project's PR quality criteria after multiple opportunities to fix. | | `suspicious_changes` | TODO: e.g. `suspicious changes` | Applied to first-time-contributor workflow approvals where the diff looks suspicious (binary blobs, unrelated CI changes, etc.). | | `work_in_progress` | TODO: e.g. `WIP` (or blank if the project doesn't use a WIP label) | Trips the skill's "leave alone" decision for in-progress PRs. | diff --git a/projects/_template/pr-triage-ci-check-map.md b/projects/_template/pr-management-triage-ci-check-map.md similarity index 90% rename from projects/_template/pr-triage-ci-check-map.md rename to projects/_template/pr-management-triage-ci-check-map.md index 18a555ed..73311cde 100644 --- a/projects/_template/pr-triage-ci-check-map.md +++ b/projects/_template/pr-management-triage-ci-check-map.md @@ -2,7 +2,7 @@ **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* -- [TODO: `` — pr-triage CI-check to doc-URL map](#todo-project-name--pr-triage-ci-check-to-doc-url-map) +- [TODO: `` — pr-management-triage CI-check to doc-URL map](#todo-project-name--pr-management-triage-ci-check-to-doc-url-map) - [Table](#table) - [Notes](#notes) @@ -11,10 +11,10 @@ -# TODO: `` — pr-triage CI-check to doc-URL map +# TODO: `` — pr-management-triage CI-check to doc-URL map This file is the **CI-check categorisation table** for the -[`pr-triage`](../../.claude/skills/pr-triage/SKILL.md) skill's +[`pr-management-triage`](../../.claude/skills/pr-management-triage/SKILL.md) skill's violations comments. When a PR has failing CI checks, the skill groups the failures by category (static checks, tests, image builds, etc.) and links each category to the project's diff --git a/projects/_template/pr-triage-comment-templates.md b/projects/_template/pr-management-triage-comment-templates.md similarity index 85% rename from projects/_template/pr-triage-comment-templates.md rename to projects/_template/pr-management-triage-comment-templates.md index 12de2f78..ca77293d 100644 --- a/projects/_template/pr-triage-comment-templates.md +++ b/projects/_template/pr-management-triage-comment-templates.md @@ -2,7 +2,7 @@ **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* -- [TODO: `` — pr-triage comment templates](#todo-project-name--pr-triage-comment-templates) +- [TODO: `` — pr-management-triage comment templates](#todo-project-name--pr-management-triage-comment-templates) - [Project-specific URLs](#project-specific-urls) - [Quality-criteria marker string](#quality-criteria-marker-string) - [AI-attribution footer](#ai-attribution-footer) @@ -13,11 +13,11 @@ -# TODO: `` — pr-triage comment templates +# TODO: `` — pr-management-triage comment templates This file is the **per-project comment-body library** for the -[`pr-triage`](../../.claude/skills/pr-triage/SKILL.md) skill. The -framework's [`comment-templates.md`](../../.claude/skills/pr-triage/comment-templates.md) +[`pr-management-triage`](../../.claude/skills/pr-management-triage/SKILL.md) skill. The +framework's [`comment-templates.md`](../../.claude/skills/pr-management-triage/comment-templates.md) documents what each template **must** contain (the contract); this file is where the adopter declares the project's actual wording, URLs, and tone. @@ -30,7 +30,7 @@ recognise the voice across repeated triage cycles. ## Project-specific URLs Plug these placeholders into the templates below. The framework's -[`comment-templates.md`](../../.claude/skills/pr-triage/comment-templates.md) +[`comment-templates.md`](../../.claude/skills/pr-management-triage/comment-templates.md) references each by name. | Placeholder | Project value | @@ -44,7 +44,7 @@ references each by name. The framework uses a literal string to detect already-triaged PRs (searches the PR body and comments for it). **Do not paraphrase**: the same exact string must appear verbatim in every triage comment -the skill posts, and the `pr-stats` skill uses the same marker for +the skill posts, and the `pr-management-stats` skill uses the same marker for "is this PR triaged" detection. | Concept | Default value | Project value | @@ -54,7 +54,7 @@ the skill posts, and the `pr-stats` skill uses the same marker for ## AI-attribution footer The verbatim block appended to every contributor-facing comment -(see [`comment-templates.md`](../../.claude/skills/pr-triage/comment-templates.md#ai-attribution-footer) +(see [`comment-templates.md`](../../.claude/skills/pr-management-triage/comment-templates.md#ai-attribution-footer) for the rules — always-include, never-paraphrase, render at end of body). Customise the **wording** for the project but keep the **structure** (italicised meta-block, link to two-stage-triage @@ -68,7 +68,7 @@ _Note: This comment was drafted by an AI-assisted triage tool and may contain mi ## Template bodies -The framework's [`comment-templates.md`](../../.claude/skills/pr-triage/comment-templates.md) +The framework's [`comment-templates.md`](../../.claude/skills/pr-management-triage/comment-templates.md) documents the seven template categories the skill emits: 1. `draft` — convert-to-draft body diff --git a/projects/_template/scope-labels.md b/projects/_template/scope-labels.md index 4a7dd813..d54733de 100644 --- a/projects/_template/scope-labels.md +++ b/projects/_template/scope-labels.md @@ -26,7 +26,7 @@ handling process (valid/invalid consensus landed). The scope: table below). TODO: list the project's scope labels, one row per label. If a report -affects more than one scope, the `security-sync-issues` skill surfaces +affects more than one scope, the `security-issue-sync` skill surfaces this as a blocker and the triager splits the report into per-scope trackers. diff --git a/projects/_template/title-normalization.md b/projects/_template/title-normalization.md index 8233364e..13432ea7 100644 --- a/projects/_template/title-normalization.md +++ b/projects/_template/title-normalization.md @@ -21,7 +21,7 @@ should be the **bare description** — no project prefix, no redundant version suffix, no reporter-added tag like `[ Security Report ]`. -The [`security-allocate-cve`](../../.claude/skills/security-allocate-cve/SKILL.md) +The [`security-cve-allocate`](../../.claude/skills/security-cve-allocate/SKILL.md) skill reads this file for the exact strip cascade to apply to the tracker title before pasting it into the allocation form. @@ -68,7 +68,7 @@ in this file once you settle on it. ## Sanity check Show the stripped title and the original title side by side in the -security-allocate-cve proposal so the user can spot any over-stripping +security-cve-allocate proposal so the user can spot any over-stripping before pasting into the CVE tool. If the strip collapses the title to fewer than 3 words, surface that as a warning and propose a manual override — over-stripping is worse than leaving one diff --git a/secure-agent-internals.md b/secure-agent-internals.md index 48e8064b..1aff905c 100644 --- a/secure-agent-internals.md +++ b/secure-agent-internals.md @@ -197,7 +197,7 @@ Mitigations available today, ordered from cheapest to strongest: - Issue `Bash` calls one command at a time, not as chained pipelines. The deny pattern then matches the actual command that runs. The agent-guided - `setup-verify-secure-config` skill does this deliberately when + `setup-isolated-setup-verify` skill does this deliberately when running its denial checks. - On hosts where `Bash(*)` chained execution is a meaningful exfiltration concern, run an outbound packet filter diff --git a/secure-agent-setup.md b/secure-agent-setup.md index bd06e15a..d623a6cf 100644 --- a/secure-agent-setup.md +++ b/secure-agent-setup.md @@ -90,37 +90,37 @@ privilege-elevating runs without you saying so. ```text 1. Open Claude Code in your tracker repo (or any directory). 2. If you consume the framework as a submodule of your tracker - (the canonical adopter pattern), run /setup-verify-steward + (the canonical adopter pattern), run /setup-steward-verify to confirm `.apache-steward/`, the submodule, and the project-config under it are wired correctly. Read-only — surfaces gaps, never auto-fixes. -3. Run /setup-secure-config — guided first-time install of +3. Run /setup-isolated-setup-install — guided first-time install of the secure-agent setup (sandbox, hooks, status line, clean-env wrapper). -4. Run /setup-verify-secure-config — confirms ✓/✗/⚠ for every piece +4. Run /setup-isolated-setup-verify — confirms ✓/✗/⚠ for every piece of the secure-agent setup. 5. When you want to be on the framework's latest, run - /setup-upgrade-steward — pulls your local airflow-steward + /setup-steward-upgrade — pulls your local airflow-steward checkout to origin/main with --ff-only, refuses to touch a dirty working tree, surfaces what arrived. Then run - /setup-update-secure-config to surface user-side drift the + /setup-isolated-setup-update to surface user-side drift the upgrade introduced (new permissions.deny entries, user-scope script copies older than the framework, pinned tool bumps that warrant a host install). 6. Optional: if you maintain a private dotfile-style sync repo per [Syncing user-scope config across machines](#syncing-user-scope-config-across-machines), - run /setup-sync-shared-config to push local edits to the remote + run /setup-shared-config-sync to push local edits to the remote so other machines pick them up. ``` The skills are at -[`.claude/skills/setup-verify-steward/`](.claude/skills/setup-verify-steward/SKILL.md), -[`.claude/skills/setup-secure-config/`](.claude/skills/setup-secure-config/SKILL.md), -[`.claude/skills/setup-verify-secure-config/`](.claude/skills/setup-verify-secure-config/SKILL.md), -[`.claude/skills/setup-upgrade-steward/`](.claude/skills/setup-upgrade-steward/SKILL.md), -[`.claude/skills/setup-update-secure-config/`](.claude/skills/setup-update-secure-config/SKILL.md), -[`.claude/skills/setup-sync-shared-config/`](.claude/skills/setup-sync-shared-config/SKILL.md). +[`.claude/skills/setup-steward-verify/`](.claude/skills/setup-steward-verify/SKILL.md), +[`.claude/skills/setup-isolated-setup-install/`](.claude/skills/setup-isolated-setup-install/SKILL.md), +[`.claude/skills/setup-isolated-setup-verify/`](.claude/skills/setup-isolated-setup-verify/SKILL.md), +[`.claude/skills/setup-steward-upgrade/`](.claude/skills/setup-steward-upgrade/SKILL.md), +[`.claude/skills/setup-isolated-setup-update/`](.claude/skills/setup-isolated-setup-update/SKILL.md), +[`.claude/skills/setup-shared-config-sync/`](.claude/skills/setup-shared-config-sync/SKILL.md). Each skill references back into the canonical sections of this document rather than duplicating them, so anything the skill walks you through has a longer-form section here you can read for diff --git a/tools/cve-org/tool.md b/tools/cve-org/tool.md index e44bf17d..2e4bdb95 100644 --- a/tools/cve-org/tool.md +++ b/tools/cve-org/tool.md @@ -33,10 +33,10 @@ readable lookup. One capability: **publication state check**. Given a `CVE-ID`, answer *"is this record live on cve.org yet?"*. Used by -`security-sync-issues` to drive the *"notify the reporter that the +`security-issue-sync` to drive the *"notify the reporter that the CVE is published"* proposal (see the [*"Check recently-closed trackers for CVE publication state"* -section](../../.claude/skills/security-sync-issues/SKILL.md) +section](../../.claude/skills/security-issue-sync/SKILL.md) in the sync skill). ## URLs diff --git a/tools/github/issue-template.md b/tools/github/issue-template.md index b5a68a34..8edddcd2 100644 --- a/tools/github/issue-template.md +++ b/tools/github/issue-template.md @@ -39,12 +39,12 @@ renamed, or removed: 2. **The project manifest** — `/project.md` declares the concrete field name each skill role maps to. Renaming the field in the YAML requires updating this mapping. -3. **The skills that write fresh issue bodies** — `security-import-issues` +3. **The skills that write fresh issue bodies** — `security-issue-import` emits a heredoc body with the full field set; when the schema changes, the heredoc must change in lock-step. No skill parses the YAML at runtime. The field list is hand- -maintained in the project manifest and in the `security-import-issues` +maintained in the project manifest and in the `security-issue-import` heredoc, and the three surfaces are kept aligned by convention. ## Field roles the skills use @@ -63,7 +63,7 @@ The generic lifecycle refers to fields by these roles: | `remediation-developer` | CVE JSON generator | sync (auto-populated from `pr-with-fix` author when set; manual edits preserved) | Person(s) who authored the fix; one credit per line. | | `cwe` | CVE JSON generator | sync proposes, user confirms | CWE number for the CVE 5.x `problemTypes[]`. | | `severity` | CVE JSON generator | sync proposes, user confirms | CVSS severity; never copy the reporter's self-assigned value. | -| `cve-tool-link` | sync, security-allocate-cve (blocker check) | security-allocate-cve | Canonical link to the CVE record in the project's CVE tool. | +| `cve-tool-link` | sync, security-cve-allocate (blocker check) | security-cve-allocate | Canonical link to the CVE record in the project's CVE tool. | The concrete field names each role maps to for the adopting project live in the project manifest. diff --git a/tools/github/labels.md b/tools/github/labels.md index 6580bf93..2eb59a27 100644 --- a/tools/github/labels.md +++ b/tools/github/labels.md @@ -50,7 +50,7 @@ These are mutually exclusive — a tracker closes with exactly one of: |---|---| | `invalid` | Report is not a vulnerability per the project's Security Model. | | `not CVE worthy` | Reproducible but not severe / scoped enough to warrant a CVE (e.g. self-XSS, DoS by authenticated admin). | -| `duplicate` | Root-cause-equivalent to another tracker; kept tracker carries the CVE. See the `security-deduplicate-issues` skill. | +| `duplicate` | Root-cause-equivalent to another tracker; kept tracker carries the CVE. See the `security-issue-deduplicate` skill. | | `wontfix` | Will not be fixed (e.g. feature-not-bug, deprecated surface being removed in the next release). | ## Secondary labels @@ -64,7 +64,7 @@ These do not gate state transitions but carry coordination signals. ## Maintenance -The `security-sync-issues` skill is the authority on label transitions +The `security-issue-sync` skill is the authority on label transitions — on every run it detects the current state (labels + body fields + fix-PR state + release state) and proposes the label transitions the process requires. diff --git a/tools/github/project-board.md b/tools/github/project-board.md index ed3080ec..fbfdc870 100644 --- a/tools/github/project-board.md +++ b/tools/github/project-board.md @@ -26,7 +26,7 @@ The **project board** is the security team's primary overview surface: a Projects V2 board where every tracking issue sits in exactly one `Status` column representing its current lifecycle state. The -`security-sync-issues` skill reads the current column as part of its +`security-issue-sync` skill reads the current column as part of its state-gather, and reconciles it against the issue's labels + body state as part of its apply loop. @@ -59,7 +59,7 @@ security tracker carries the label: 1. The repo's [issue template](issue-template.md) lists `security issue` in its `labels:` frontmatter, so any tracker created via *New issue → Airflow Security Issue* gets the label automatically. -2. The `security-import-issues` skill passes `--label 'security issue'` +2. The `security-issue-import` skill passes `--label 'security issue'` on every `gh issue create` it runs. Manually-opened issues (no template, no skill) will not appear on the diff --git a/tools/github/status-rollup.md b/tools/github/status-rollup.md index 8b2f9d01..0d28b8f4 100644 --- a/tools/github/status-rollup.md +++ b/tools/github/status-rollup.md @@ -116,14 +116,14 @@ line tells the reader at a glance *what* the entry represents: | Emitting skill | `` value | Optional parenthetical | |---|---|---| -| `security-import-issues` | `Import` | class + reporter, e.g. `Import (Report, Jane Doe)` | -| `security-sync-issues` (ordinary pass) | `Sync` | one-phrase headline, e.g. `Sync (pr merged → fix released)` | -| `security-sync-issues` (escalation, Step 4) | `Sync` | `Sync (Step 4 escalation)` | -| `security-sync-issues` (reformat-only, migrating legacy comments) | `Reformat` | `Reformat (N legacy comments folded)` | -| `security-allocate-cve` | `CVE allocated` | the allocated ID, e.g. `CVE allocated (CVE-2026-40913)` | -| `security-deduplicate-issues`, on the kept tracker | `Merge (kept)` | dropped side's number, e.g. `Merge (kept) (from #305)` | -| `security-deduplicate-issues`, on the dropped tracker | `Merge (dropped)` | kept side's number, e.g. `Merge (dropped) (into #244)` | -| `security-fix-issue` | `Fix PR` | upstream PR number, e.g. `Fix PR (#65346)` | +| `security-issue-import` | `Import` | class + reporter, e.g. `Import (Report, Jane Doe)` | +| `security-issue-sync` (ordinary pass) | `Sync` | one-phrase headline, e.g. `Sync (pr merged → fix released)` | +| `security-issue-sync` (escalation, Step 4) | `Sync` | `Sync (Step 4 escalation)` | +| `security-issue-sync` (reformat-only, migrating legacy comments) | `Reformat` | `Reformat (N legacy comments folded)` | +| `security-cve-allocate` | `CVE allocated` | the allocated ID, e.g. `CVE allocated (CVE-2026-40913)` | +| `security-issue-deduplicate`, on the kept tracker | `Merge (kept)` | dropped side's number, e.g. `Merge (kept) (from #305)` | +| `security-issue-deduplicate`, on the dropped tracker | `Merge (dropped)` | kept side's number, e.g. `Merge (dropped) (into #244)` | +| `security-issue-fix` | `Fix PR` | upstream PR number, e.g. `Fix PR (#65346)` | The parenthetical is optional; include it when it adds information a scroller actually wants (the CVE ID, the dedupe counterpart, the PR @@ -181,7 +181,7 @@ gh issue view --repo \ The matching comment is the rollup. If the query returns nothing, there is no rollup yet (expected on a fresh tracker where -`security-import-issues` has not run, or on a legacy tracker that +`security-issue-import` has not run, or on a legacy tracker that pre-dates this convention). Use the **first** match chronologically if the query somehow returns @@ -277,7 +277,7 @@ A comment is a candidate for folding when **all** of the following hold: - Legacy bare-text prefixes (no leading `**`): `Sync status (`, `Sync YYYY-MM-DD`, `Status update` - Content tells when the prefix is idiosyncratic: - `security-sync-issues skill`, `re-triage`, + `security-issue-sync skill`, `re-triage`, `Reporter notification still pending`, `Outstanding — Step `, a verbatim `generate-cve-json` embed block. @@ -383,8 +383,8 @@ audit the change. ## Referenced by -- [`.claude/skills/security-import-issues/SKILL.md`](../../.claude/skills/security-import-issues/SKILL.md) — creates the rollup with the first entry. -- [`.claude/skills/security-sync-issues/SKILL.md`](../../.claude/skills/security-sync-issues/SKILL.md) — appends per-sync entries and runs the fold-legacy sub-step. -- [`.claude/skills/security-allocate-cve/SKILL.md`](../../.claude/skills/security-allocate-cve/SKILL.md) — appends the CVE-allocation entry. -- [`.claude/skills/security-deduplicate-issues/SKILL.md`](../../.claude/skills/security-deduplicate-issues/SKILL.md) — appends the merge entry on both trackers. -- [`.claude/skills/security-fix-issue/SKILL.md`](../../.claude/skills/security-fix-issue/SKILL.md) — appends the fix-PR entry. +- [`.claude/skills/security-issue-import/SKILL.md`](../../.claude/skills/security-issue-import/SKILL.md) — creates the rollup with the first entry. +- [`.claude/skills/security-issue-sync/SKILL.md`](../../.claude/skills/security-issue-sync/SKILL.md) — appends per-sync entries and runs the fold-legacy sub-step. +- [`.claude/skills/security-cve-allocate/SKILL.md`](../../.claude/skills/security-cve-allocate/SKILL.md) — appends the CVE-allocation entry. +- [`.claude/skills/security-issue-deduplicate/SKILL.md`](../../.claude/skills/security-issue-deduplicate/SKILL.md) — appends the merge entry on both trackers. +- [`.claude/skills/security-issue-fix/SKILL.md`](../../.claude/skills/security-issue-fix/SKILL.md) — appends the fix-PR entry. diff --git a/tools/gmail/asf-relay.md b/tools/gmail/asf-relay.md index cdf0297f..81bde08e 100644 --- a/tools/gmail/asf-relay.md +++ b/tools/gmail/asf-relay.md @@ -62,7 +62,7 @@ Placeholder convention: ## How the skills detect relay cases -The `security-import-issues` skill classifies candidates into +The `security-issue-import` skill classifies candidates into `Report`, `ASF-security relay`, and several non-import classes; the classification feeds this drafting path. diff --git a/tools/gmail/draft-backends.md b/tools/gmail/draft-backends.md index 69fa29fd..ff64002b 100644 --- a/tools/gmail/draft-backends.md +++ b/tools/gmail/draft-backends.md @@ -175,8 +175,8 @@ to the user before drafting a new one"*. Caught live on 2026-04-25 during the [`#346`](https://github.com//issues/346) fix-skill flow: when **multiple `oauth_curl`-backed drafts pile up on the same Gmail thread** within a single skill flow (typical sequence: -security-allocate-cve drafts a CVE-allocated message → security-sync-issues -drafts a corrected version with updated state → security-fix-issue +security-cve-allocate drafts a CVE-allocated message → security-issue-sync +drafts a corrected version with updated state → security-issue-fix drafts the final version after a state change), the drafts all carry the `DRAFT` label in the Gmail API but **only the most recent surfaces in the user's global Drafts folder in Gmail's UI**. The earlier ones diff --git a/tools/gmail/operations.md b/tools/gmail/operations.md index 3385cbff..c45a735b 100644 --- a/tools/gmail/operations.md +++ b/tools/gmail/operations.md @@ -73,7 +73,7 @@ mcp__claude_ai_Gmail__search_threads( ``` Returns an array of `{threadId, snippet, …}` objects. Use `pageSize` -deliberately — some skills (e.g. `security-sync-issues`) impose a +deliberately — some skills (e.g. `security-issue-sync`) impose a hard Gmail-call budget per issue to avoid running up the MCP quota on many-tracker sweeps. @@ -92,7 +92,7 @@ mcp__claude_ai_Gmail__get_thread( Returns the full message history of a thread. Body reads are expensive — most skills filter candidates down on metadata first and only fetch bodies for the narrow set that actually warrants it -(`security-import-issues` does this explicitly at Step 3). +(`security-issue-import` does this explicitly at Step 3). ## Write — drafts only, never send @@ -190,7 +190,7 @@ mcp__claude_ai_Gmail__list_drafts( ) ``` -Used by `security-sync-issues` to verify that a draft flagged as stale +Used by `security-issue-sync` to verify that a draft flagged as stale in a previous status comment still exists before carrying the flag forward. See the *"self-replicating stale-draft flag"* paragraph in that skill. diff --git a/tools/gmail/ponymail-archive.md b/tools/gmail/ponymail-archive.md index 97989a54..0fbd9b2c 100644 --- a/tools/gmail/ponymail-archive.md +++ b/tools/gmail/ponymail-archive.md @@ -7,8 +7,8 @@ - [Archive search (query returns a list-page with matching threads)](#archive-search-query-returns-a-list-page-with-matching-threads) - [Archive API (JSON response, the sync skill uses this first)](#archive-api-json-response-the-sync-skill-uses-this-first) - [Resolved thread URL (what the skill records in the tracker)](#resolved-thread-url-what-the-skill-records-in-the-tracker) - - [Use case — `security-import-issues`](#use-case--security-import-issues) - - [Use case — `security-sync-issues`](#use-case--security-sync-issues) + - [Use case — `security-issue-import`](#use-case--security-issue-import) + - [Use case — `security-issue-sync`](#use-case--security-issue-sync) - [When the archive is not available](#when-the-archive-is-not-available) @@ -97,7 +97,7 @@ field (for public lookups). Field-role names are defined in [`../github/issue-template.md`](../github/issue-template.md#field-roles-the-skills-use); project-specific concrete field names live in the project manifest. -## Use case — `security-import-issues` +## Use case — `security-issue-import` The security list's PonyMail archive is not anonymously queryable (the list is gated behind ASF LDAP), so the skill **cannot** fetch @@ -127,7 +127,7 @@ CVE-JSON generator does not export it to `references[]`. See the *"CVE references must never point at non-public mailing-list threads"* rule in [`../../AGENTS.md`](../../AGENTS.md). -## Use case — `security-sync-issues` +## Use case — `security-issue-sync` The public `users@` archive **is** anonymously queryable. On every sync run, if the tracker has `announced - emails sent` but the diff --git a/tools/gmail/search-queries.md b/tools/gmail/search-queries.md index dc627496..ed39b626 100644 --- a/tools/gmail/search-queries.md +++ b/tools/gmail/search-queries.md @@ -6,10 +6,10 @@ - [Gmail operator cheat-sheet](#gmail-operator-cheat-sheet) - [GitHub-notification exclusions](#github-notification-exclusions) - [Query templates by skill](#query-templates-by-skill) - - [`security-import-issues` — candidate-listing query](#security-import-issues--candidate-listing-query) - - [`security-import-issues` — prior-rejection search](#security-import-issues--prior-rejection-search) - - [`security-sync-issues` — reporter-thread lookup by distinctive phrase](#security-sync-issues--reporter-thread-lookup-by-distinctive-phrase) - - [`security-sync-issues` — CVE-review-comment search](#security-sync-issues--cve-review-comment-search) + - [`security-issue-import` — candidate-listing query](#security-issue-import--candidate-listing-query) + - [`security-issue-import` — prior-rejection search](#security-issue-import--prior-rejection-search) + - [`security-issue-sync` — reporter-thread lookup by distinctive phrase](#security-issue-sync--reporter-thread-lookup-by-distinctive-phrase) + - [`security-issue-sync` — CVE-review-comment search](#security-issue-sync--cve-review-comment-search) - [Release `[RESULT][VOTE]` attribution](#release-resultvote-attribution) - [Budget discipline](#budget-discipline) @@ -69,7 +69,7 @@ the list), trim or replace these as needed. ## Query templates by skill -### `security-import-issues` — candidate-listing query +### `security-issue-import` — candidate-listing query Inbound threads that might be new reports, minus GitHub-notification bots, within a time window: @@ -94,7 +94,7 @@ instead. Adjust the time window per the user's selector (`since:` → `newer_than:` or `after:`; `import all` → `newer_than:90d`). -### `security-import-issues` — prior-rejection search +### `security-issue-import` — prior-rejection search Run in Step 2b of the import skill on candidates heading for a negative-response disposition. The goal is to find **prior similar @@ -155,7 +155,7 @@ roster member, or rely on `list:` + the no-`from:notifications@github.com` filter as in template 1 and classify the result set by sender after the fact. -### `security-sync-issues` — reporter-thread lookup by distinctive phrase +### `security-issue-sync` — reporter-thread lookup by distinctive phrase When a tracking issue's GitHub title does not match the original email subject (common — the triager paraphrases the subject when @@ -172,7 +172,7 @@ Pick a phrase that is rare in the security list's volume — a function name, an endpoint path, an error string — rather than a common word. -### `security-sync-issues` — CVE-review-comment search +### `security-issue-sync` — CVE-review-comment search The project's CVE tool (Vulnogram for ASF) notifies the security list by email when a reviewer leaves a comment on the CVE record. @@ -213,8 +213,8 @@ the project's release-trains file (for Airflow, Gmail MCP calls are metered. Skill-level rules: -- `security-import-issues` runs exactly one list scan per invocation. -- `security-sync-issues` runs at most one reporter-thread search + +- `security-issue-import` runs exactly one list scan per invocation. +- `security-issue-sync` runs at most one reporter-thread search + two CVE-review searches per tracking issue (i.e. ≤ 3 per tracker; ≤ ~60 on a 20-tracker sweep). - No skill retries on its own. If a search fails, surface the diff --git a/tools/gmail/tool.md b/tools/gmail/tool.md index e6919788..d3ce70f9 100644 --- a/tools/gmail/tool.md +++ b/tools/gmail/tool.md @@ -40,7 +40,7 @@ Related, adjacent tool: | Capability | File | What it covers | |---|---|---| -| ASF PonyMail archive lookups | [`ponymail-archive.md`](ponymail-archive.md) | URL-construction pattern for the ASF's `lists.apache.org` archive (used by `security-sync-issues` to scan the public `users@` archive for the advisory URL, and by `security-import-issues` to resolve a pastable thread URL for the private `security@` list) | +| ASF PonyMail archive lookups | [`ponymail-archive.md`](ponymail-archive.md) | URL-construction pattern for the ASF's `lists.apache.org` archive (used by `security-issue-sync` to scan the public `users@` archive for the advisory URL, and by `security-issue-import` to resolve a pastable thread URL for the private `security@` list) | ## Why this is its own tool diff --git a/tools/ponymail/operations.md b/tools/ponymail/operations.md index 38737a76..62176d9c 100644 --- a/tools/ponymail/operations.md +++ b/tools/ponymail/operations.md @@ -273,7 +273,7 @@ mcp__ponymail__search_list( Filter by a distinctive function name, endpoint path, or error string — same heuristic as the Gmail equivalent in -[`../gmail/search-queries.md`](../gmail/search-queries.md#security-sync-issues--reporter-thread-lookup-by-distinctive-phrase). +[`../gmail/search-queries.md`](../gmail/search-queries.md#security-issue-sync--reporter-thread-lookup-by-distinctive-phrase). ### Find the `[RESULT][VOTE]` thread for a release diff --git a/tools/vulnogram/allocation.md b/tools/vulnogram/allocation.md index b02e0be5..4004a643 100644 --- a/tools/vulnogram/allocation.md +++ b/tools/vulnogram/allocation.md @@ -20,7 +20,7 @@ The Vulnogram-side mechanics of CVE allocation (step 6 of the generic handling process in [`../../README.md`](../../README.md)). The generic flow of *"walk the triager through an allocation, capture the ID, wire it into the tracker"* lives in the -[`security-allocate-cve`](../../.claude/skills/security-allocate-cve/SKILL.md) skill; +[`security-cve-allocate`](../../.claude/skills/security-cve-allocate/SKILL.md) skill; this file documents the **Vulnogram-specific** parts that skill reads. Per-project configuration (allocation URL, record URL template, org @@ -47,7 +47,7 @@ project the allocation is against. This is not something the skill can work around — a non-PMC user who clicks *Allocate* sees the button grey out. -**Practical consequence.** The `security-allocate-cve` skill asks up front +**Practical consequence.** The `security-cve-allocate` skill asks up front *"are you a PMC member?"*: - **PMC** — recipe is self-service: click the URL, paste the title, @@ -56,7 +56,7 @@ button grey out. a comment on the tracker (`@`-mentioning a PMC member) or sends on the project's `security_list`. The PMC member reads the relay, clicks through, allocates, and posts the ID back. The original - triager (or the PMC member) can then re-invoke `security-allocate-cve` with + triager (or the PMC member) can then re-invoke `security-cve-allocate` with the CVE ID as an override to resume from the wire-back step. Concrete PMC-member handles live in the project's roster file (for @@ -75,13 +75,13 @@ source is the ASF project page, | **Summary** | Tracker body's *public-summary* field. | | **Reporter credits** | Tracker body's *reporter-credit* field. | -The `security-allocate-cve` skill renders this mapping as a numbered recipe +The `security-cve-allocate` skill renders this mapping as a numbered recipe the user copy-pastes into the form in one pass. ## After the CVE is allocated Once the PMC member has reported the `CVE-YYYY-NNNNN` back, the -`security-allocate-cve` skill wires it into the tracker in one coordinated +`security-cve-allocate` skill wires it into the tracker in one coordinated pass — the generic steps (populate the *cve-tool-link* body field, add the `cve allocated` label, post a status-change comment, regenerate the CVE JSON attachment, draft a reporter status update) @@ -100,6 +100,6 @@ are tool-agnostic; the Vulnogram-specific output is: Allocating a CVE against the wrong product (e.g. `apache-airflow` when the fix actually lives in `apache-airflow-providers-smtp`) is a multi-hour cleanup involving Vulnogram support and the release -manager. The `security-allocate-cve` skill's Step 1 blocker checks refuse to +manager. The `security-cve-allocate` skill's Step 1 blocker checks refuse to proceed without a scope label precisely because of this — see the skill file for the hard-check details. diff --git a/tools/vulnogram/generate-cve-json/SKILL.md b/tools/vulnogram/generate-cve-json/SKILL.md index 6362ff2d..1ced0160 100644 --- a/tools/vulnogram/generate-cve-json/SKILL.md +++ b/tools/vulnogram/generate-cve-json/SKILL.md @@ -70,7 +70,7 @@ diff the two to see what the tool has added / what you changed by hand. - `--remediation-developer "Name"` — append a `type: "remediation developer"` credit on top of whatever the body's *Remediation developer* field already lists (auto-populated by the - `security-sync-issues` skill from the linked PR's author). Repeat + `security-issue-sync` skill from the linked PR's author). Repeat the flag to add multiple developers; duplicates between the body field and CLI flags are dropped silently. The reporter credit(s) from the *Reporter credited as* field are always @@ -114,7 +114,7 @@ diff the two to see what the tool has added / what you changed by hand. ## Prerequisites on the tracking issue For the generated JSON to be useful, the issue body should already be -filled in through a prior `security-sync-issues` run. In particular: +filled in through a prior `security-issue-sync` run. In particular: - **Short public summary for publish** — becomes the CVE description. - **Affected versions** — becomes the CVE `affected[]` list. The script @@ -152,7 +152,7 @@ filled in through a prior `security-sync-issues` run. In particular: emits a `versions[]` entry without `lessThan` (open-ended upper bound — *"affected from \ onwards, no fix released yet"*). When the wave ships and the version is known, the - `security-sync-issues` skill replaces each `NEXT VERSION` with the + `security-issue-sync` skill replaces each `NEXT VERSION` with the actual `< X.Y.Z` and the next regen produces a fully-bounded entry. Case-insensitive; combines with a lower bound (e.g. `>= 2.0.0, < NEXT VERSION` becomes `{version: "2.0.0", status: "affected"}`). @@ -161,7 +161,7 @@ filled in through a prior `security-sync-issues` run. In particular: `references[]`. Keep whatever the reporter or triager put there. - **Public advisory URL** — each URL in this field is extracted and added to `references[]` with `tags: ["vendor-advisory"]`. Populated - by the release manager (or the `security-sync-issues` skill) once + by the release manager (or the `security-issue-sync` skill) once the advisory is archived on ``. The `--advisory-url` CLI flag still exists for ad-hoc overrides. - **PR with the fix** — each URL in this field becomes a reference URL. @@ -184,7 +184,7 @@ filled in through a prior `security-sync-issues` run. In particular: with `type: "remediation developer"`. Same parsing rules as *Reporter credited as* (newline-separated, `Full Name, Affiliation` is one credit, bullets stripped). Auto-populated by the - `security-sync-issues` skill from the linked PR's author the first + `security-issue-sync` skill from the linked PR's author the first time *PR with the fix* is set; manual edits survive subsequent syncs (the skill only proposes appending names that aren't already there). The `--remediation-developer` CLI flag adds further names @@ -240,7 +240,7 @@ in to. Fetch the issue body and check every template field the script reads. If a field is missing or still `_No response_`, either run -[`security-sync-issues`](../../../.claude/skills/security-sync-issues/SKILL.md) first to fill it +[`security-issue-sync`](../../../.claude/skills/security-issue-sync/SKILL.md) first to fill it in, or override it on the command line. ```bash @@ -270,7 +270,7 @@ uv run --project /tools/vulnogram/generate-cve-json generate-cve-json contains and that Vulnogram expects filled in (the body field usually encodes only the upper bound). The remediation developer credit comes from the body's *Remediation developer* field, populated by the -`security-sync-issues` skill from the linked PR's author — no CLI flag +`security-issue-sync` skill from the linked PR's author — no CLI flag needed in the normal flow. For a fix that landed in `3.2.2` and was first introduced in `3.0.0`, for example: @@ -464,7 +464,7 @@ the local JSON file to match tool-side changes. Re-run the script instead output against the current Vulnogram state, and paste the merged JSON back. This keeps the tracking issue as the single source of truth: if Vulnogram shows something different from the generated JSON, either the -issue body is out of date and needs a `security-sync-issues` run, or the +issue body is out of date and needs a `security-issue-sync` run, or the tool-side difference is intentional and the reviewer will keep it. --- @@ -511,8 +511,8 @@ tool-side difference is intentional and the reviewer will keep it. step 13 (fill in CVE tool fields and send advisory from the tool) and step 15 (paste the attached JSON into Vulnogram's #source tab, move the CVE to PUBLIC, close the issue). -- [`security-sync-issues`](../../../.claude/skills/security-sync-issues/SKILL.md) — the sibling +- [`security-issue-sync`](../../../.claude/skills/security-issue-sync/SKILL.md) — the sibling skill that populates the tracking issue fields this skill consumes. -- [`security-fix-issue`](../../../.claude/skills/security-fix-issue/SKILL.md) — the other +- [`security-issue-fix`](../../../.claude/skills/security-issue-fix/SKILL.md) — the other sibling skill that opens a public PR and updates the tracking issue with the fix URL. diff --git a/tools/vulnogram/generate-cve-json/src/generate_cve_json/cve_json.py b/tools/vulnogram/generate-cve-json/src/generate_cve_json/cve_json.py index 0a59660a..6dfa2475 100644 --- a/tools/vulnogram/generate-cve-json/src/generate_cve_json/cve_json.py +++ b/tools/vulnogram/generate-cve-json/src/generate_cve_json/cve_json.py @@ -481,7 +481,7 @@ def parse_affected_versions(value: str, version_start_override: str | None) -> l sync skill replaces ``< NEXT VERSION`` with the actual ``< X.Y.Z`` upper bound and the next regen produces a fully-bounded entry. See the ``NEXT VERSION`` rule in - ``.claude/skills/security-sync-issues/SKILL.md`` for the lifecycle. + ``.claude/skills/security-issue-sync/SKILL.md`` for the lifecycle. ``--version-start`` overrides the low bound unconditionally when set, because the issue body rarely specifies it and a reviewer usually @@ -1547,7 +1547,7 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace: "Name to add to `credits[]` with type 'remediation developer'. " "In normal use, the developer name lives in the issue body's " "*Remediation developer* field (auto-populated by the " - "`security-sync-issues` skill from the linked PR's author). " + "`security-issue-sync` skill from the linked PR's author). " "This flag is an additional / override mechanism: names " "passed here are appended to whatever the body already " "specifies, with duplicates silently dropped. Repeat the " @@ -1705,7 +1705,7 @@ def main(argv: list[str] | None = None) -> int: description = summary or title # Advisory URLs come from two sources: the body's "Public advisory URL" - # field (populated by the release manager / security-sync-issues skill + # field (populated by the release manager / security-issue-sync skill # once the advisory is archived on users@airflow.apache.org) and any # --advisory-url CLI overrides. Both are forwarded to the references # builder; de-duplication happens there. diff --git a/tools/vulnogram/record.md b/tools/vulnogram/record.md index 31e6bd0e..a4a21e06 100644 --- a/tools/vulnogram/record.md +++ b/tools/vulnogram/record.md @@ -93,7 +93,7 @@ expects when the release manager triggers the advisory email send. **`READY` → `PUBLIC`** is a human release-manager click in Vulnogram after the advisory archive URL has been captured on the tracker. The -generic `security-sync-issues` skill's Step 2b does not propose this +generic `security-issue-sync` skill's Step 2b does not propose this transition — it is a Step 15 release-manager action. The publication-ready notification comment (see [*Release-manager checklist*](#release-manager-checklist) below) @@ -119,9 +119,9 @@ whether reviewer comments are still pending. ASF CNA reviewers leave comments on `REVIEW`-state records. Those comments do **not** surface on the tracking issue directly — Vulnogram notifies by email to the project's `security_list` -instead, with the CVE ID in the subject line. The `security-sync-issues` +instead, with the CVE ID in the subject line. The `security-issue-sync` skill's Step 1e reads those emails (Gmail search recipe lives in -[`../gmail/search-queries.md`](../gmail/search-queries.md#security-sync-issues--cve-review-comment-search)) +[`../gmail/search-queries.md`](../gmail/search-queries.md#security-issue-sync--cve-review-comment-search)) and surfaces each open reviewer comment in Step 2b as an actionable body-field proposal on the tracker. @@ -137,7 +137,7 @@ OAuth-gated and not readable from skill context). The `cveprocess.apache.org/cve5/.json` endpoint exists but is behind ASF OAuth and is **not** readable from agent-skill -context — the `security-sync-issues` skill therefore never curls it; +context — the `security-issue-sync` skill therefore never curls it; Gmail is the load-bearing signal source. ## Record-generator round trip @@ -161,7 +161,7 @@ has one canonical JSON to paste into `#source` at step 15. ## Release-manager checklist When the `` release containing a fix ships, the -`security-sync-issues` skill swaps the tracker's `pr merged` label to +`security-issue-sync` skill swaps the tracker's `pr merged` label to `fix released`, reassigns the issue to the release manager, and posts an explicit **release-manager hand-off comment** on the tracker (the template body lives in @@ -182,7 +182,7 @@ and **three** when reviewer comments arrive: 2. **(conditional) Re-paste after reviewer comments.** ASF CNA reviewers may leave comments while the record sits in `REVIEW` (see [*Reviewer-comment signal*](#reviewer-comment-signal) above). - The `security-sync-issues` skill detects them automatically and + The `security-issue-sync` skill detects them automatically and proposes matching body-field updates on the tracker; the security team confirms and the embedded JSON regenerates. Once the body has settled (no more pending reviewer-comment proposals), re-paste the @@ -208,7 +208,7 @@ and **three** when reviewer comments arrive: `announced - emails sent` label and remove `fix released`. 6. **Wait for the publication-ready notification comment.** The - `security-sync-issues` skill scans the public users-list archive + `security-issue-sync` skill scans the public users-list archive for the CVE ID on every run. Once it finds the archived advisory, it populates the tracker's *Public advisory URL* body field, regenerates the CVE JSON to carry the archive URL as a @@ -225,7 +225,7 @@ and **three** when reviewer comments arrive: The record propagates to `cve.org` once the state lands. 8. **Close the tracker.** Close as completed; do not update any - labels. The `security-sync-issues` skill's apply step archives the + labels. The `security-issue-sync` skill's apply step archives the project-board item afterwards (per the *archive-from-board* recipe in [`../github/project-board.md`](../github/project-board.md)) so the closed tracker leaves the active board. diff --git a/tools/vulnogram/release-manager-handoff-comment.md b/tools/vulnogram/release-manager-handoff-comment.md index b05f7cd4..4fc50252 100644 --- a/tools/vulnogram/release-manager-handoff-comment.md +++ b/tools/vulnogram/release-manager-handoff-comment.md @@ -12,7 +12,7 @@