This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch adopt-magpie-and-upgrade-hooks
in repository https://gitbox.apache.org/repos/asf/airflow-ci-infra.git

commit b40f0826da6c6e8dbb1ea8974cb6ac769060dbcf
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sun Oct 25 11:40:45 2026 +0100

    Adopt Apache Magpie and upgrade the pre-commit hooks
    
    Commit the Magpie floor (.apache-magpie.lock), the Claude Code plugin
    wiring derived from it, and the project's configuration store in
    .apache-magpie-overrides/.
    
    Upgrade every pre-commit hook, replace flake8 with ruff, and add a
    Markdown license hook. Add Dependabot for pre-commit, GitHub Actions,
    pip and Terraform, with a seven-day cooldown.
    
    Generated-by: Claude Opus 5
---
 .apache-magpie-overrides/README.md                 |  42 ++
 .../commit-attribution.toml                        |  28 +-
 .apache-magpie-overrides/project.md                | 723 +++++++++++++++++++++
 .apache-magpie-overrides/repo-health-config.md     | 191 ++++++
 .flake8 => .apache-magpie.lock                     |  26 +-
 .asf.yaml                                          |  17 +
 .claude/settings.json                              |  17 +
 .github/dependabot.yml                             |  67 ++
 .gitignore                                         |  20 +
 .pre-commit-config.yaml                            |  41 +-
 .../packer/files/runner-supervisor.py              |   7 +-
 pyproject.toml                                     |   8 +
 requirements-test.txt                              |  17 +
 scripts/list_committers                            |  16 +-
 14 files changed, 1181 insertions(+), 39 deletions(-)

diff --git a/.apache-magpie-overrides/README.md 
b/.apache-magpie-overrides/README.md
new file mode 100644
index 0000000..0972dd6
--- /dev/null
+++ b/.apache-magpie-overrides/README.md
@@ -0,0 +1,42 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+
+# apache-magpie overrides
+
+Agent-readable instructions that override specific steps or
+behaviours of apache-magpie framework skills, scoped to
+this adopter repo. Each override file is named after the
+framework skill it modifies (e.g. `pr-management-triage.md`
+overrides the `pr-management-triage` skill).
+
+The framework skills consult this directory at run-time
+before executing default behaviour. See
+[`docs/setup/agentic-overrides.md`](https://github.com/apache/magpie/blob/main/docs/setup/agentic-overrides.md)
+in the framework for the full contract.
+
+**Hard rule**: never modify the snapshot under
+`<repo-root>/.apache-magpie/`. Local mods go here.
+Framework changes go via PR to `apache/magpie`.
+
+**Personal (non-shared) overrides** belong in
+`<repo-root>/.apache-magpie-local/` (gitignored; a linked worktree
+without its own falls back to the main checkout's). Use that
+directory for per-developer paths, local tooling, or role-
+specific capability enablements you do not want committed
+to this repo.
diff --git a/pyproject.toml b/.apache-magpie-overrides/commit-attribution.toml
similarity index 50%
copy from pyproject.toml
copy to .apache-magpie-overrides/commit-attribution.toml
index 0333bb0..20aca87 100644
--- a/pyproject.toml
+++ b/.apache-magpie-overrides/commit-attribution.toml
@@ -14,15 +14,21 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-[tool.black]
-line-length = 110
-target-version = ['py36', 'py37', 'py38']
-skip-string-normalization = true
 
-[tool.isort]
-line_length = 110
-combine_as_imports = true
-default_section = 'THIRDPARTY'
-# Need to be consistent with the exclude config defined in 
pre-commit-config.yaml
-skip = ['build','.tox','venv']
-profile = 'black'
+# Which trailer an agent-assisted commit carries.
+# Resolution rules and the default wording of each convention:
+# docs/setup/commit-attribution.md.
+#
+# In .apache-magpie-overrides/ (committed) this is the project's policy,
+# and it wins. In the personal layer (.apache-magpie-local/ when the
+# project adopted Magpie, <git-common-dir>/apache-magpie/ otherwise) it is
+# one contributor's preference, used only when the project's file is absent
+# or says contributor-choice.
+
+# generated-by | assisted-by | co-authored-by | none | custom
+# The project's file may also say contributor-choice.
+convention = "generated-by"
+
+# Optional; required when convention = "custom".
+# Placeholders: {agent}, {model}, {email}.
+# template = "Generated-by: {agent} ({model})"
diff --git a/.apache-magpie-overrides/project.md 
b/.apache-magpie-overrides/project.md
new file mode 100644
index 0000000..8e5c886
--- /dev/null
+++ b/.apache-magpie-overrides/project.md
@@ -0,0 +1,723 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+
+<!-- SPDX-License-Identifier: Apache-2.0
+     https://www.apache.org/licenses/LICENSE-2.0 -->
+
+<!-- START doctoc generated TOC please keep comment here to allow auto update 
-->
+<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
+**Table of Contents**  *generated with 
[DocToc](https://github.com/thlorenz/doctoc)*
+
+- [Apache Airflow CI infrastructure — project 
manifest](#apache-airflow-ci-infrastructure--project-manifest)
+  - [Identity](#identity)
+  - [Repositories](#repositories)
+  - [Mailing lists](#mailing-lists)
+  - [Tools enabled](#tools-enabled)
+    - [Source control](#source-control)
+  - [CVE tooling](#cve-tooling)
+  - [GitHub project board](#github-project-board)
+  - [Project chat](#project-chat)
+  - [Mail sources](#mail-sources)
+    - [Backend declaration](#backend-declaration)
+    - [Drafting backend](#drafting-backend)
+    - [Per-backend config](#per-backend-config)
+  - [Issue-template fields](#issue-template-fields)
+  - [Security workflow configuration](#security-workflow-configuration)
+    - [CVE authority](#cve-authority)
+    - [Governance](#governance)
+    - [Security inbox](#security-inbox)
+    - [Forwarders](#forwarders)
+    - [Mail provider](#mail-provider)
+    - [Archive system](#archive-system)
+    - [Project metadata](#project-metadata)
+    - [Security cross-reference](#security-cross-reference)
+    - [Tracker](#tracker)
+    - [Advisory records](#advisory-records)
+    - [Scope detection](#scope-detection)
+    - [Release process](#release-process)
+    - [Roster](#roster)
+    - [Product](#product)
+  - [Pointers to sibling files](#pointers-to-sibling-files)
+
+<!-- END doctoc generated TOC please keep comment here to allow auto update -->
+
+<!-- SPDX-License-Identifier: Apache-2.0
+     https://www.apache.org/licenses/LICENSE-2.0 -->
+
+# Apache Airflow CI infrastructure — project manifest
+
+This is the **project configuration** for `apache/airflow-ci-infra`.
+Every skill under [`../../.claude/skills/`](../../../skills/)
+reads the project name from `<project-config>/project.md` and then loads this 
manifest to resolve project-specific identity,
+repositories, mailing lists, and references to the other files in
+this directory.
+
+**Note on Auto-sourcing:** Stable fields under Identity and Repositories
+(`upstream_repo`, `upstream_default_branch`, `product_family_url`, labels)
+can be automatically derived from GitHub repository metadata via
+`gh repo view` during `/magpie-setup:setup adopt` or `/magpie-setup:setup 
upgrade`, for
+any adopter. The **Mailing lists** are auto-sourced **only for
+`organization: ASF`** projects (from `.asf.yaml`, with `*.apache.org`
+defaults); a non-ASF `organization` fills them in by hand. Hand-editing is
+only required when a source is absent, incomplete, or you wish to override
+a derived value.
+
+Grep for `TODO` to see every field you still need to fill in:
+
+```bash
+grep -n TODO projects/<name>/project.md
+```
+
+## Identity
+
+| Key | Value |
+|---|---|
+| `organization` | `ASF` |
+| `project_name` | `Apache Airflow` |
+| `vendor` | `Apache Software Foundation` |
+| `short_name` | `airflow` |
+| `product_family_url` | `https://airflow.apache.org/` |
+
+The `vendor` / `project_name` pair is what lands in the `vendor` and
+`product` fields of the CVE 5.x record the CVE-JSON generator
+produces.
+
+## Repositories
+
+| Key | Value | Purpose |
+|---|---|---|
+| `tracker_repo` | TODO: e.g. `foo-s/foo-s` | Private security tracker (this 
repo) |
+| `tracker_repo_url` | TODO | |
+| `tracker_default_branch` | TODO: e.g. `main` | Default PR target for the 
tracker repo |
+| `tracker_project_board_url` | TODO: URL of the GitHub Project V2 board, if 
any | Security board |
+| `upstream_repo` | `apache/airflow-ci-infra` | Public codebase where fixes 
land |
+| `upstream_repo_url` | `https://github.com/apache/airflow-ci-infra` | |
+| `upstream_default_branch` | `main` | Upstream's default branch — what 
`<default-branch>` resolves to. Distinct from `tracker_default_branch` |
+| `upstream_agents_md_url` | TODO: 
`https://github.com/<upstream>/blob/main/AGENTS.md` | Conventions this repo 
mirrors |
+| `upstream_contributing_docs_url` | TODO | |
+| `upstream_genai_disclosure_anchor` | TODO: URL + anchor for the project's 
Gen-AI disclosure guideline | |
+| `upstream_security_policy_url` | TODO: 
`https://github.com/<upstream>/security/policy` | |
+| `security_pages_url` | TODO: e.g. `https://foo.apache.org/security` | Public 
security pages on the project website — updated by the release manager after 
each advisory (ASF security-committers policy step); read by 
`security-issue-sync` for the security-pages checklist reminder. Leave unset if 
the project has no security pages — the skill then uses the plain phrase 
without a link. To have sync propose the edit itself, also configure [Advisory 
records](#advisory-records) |
+
+## Mailing lists
+
+*(For `organization: ASF` projects only: auto-sourced from the `.asf.yaml`
+`notifications:` block if present, else `*.apache.org` defaults. A non-ASF
+`organization` has no `.asf.yaml` — fill these in by hand.)*
+
+| Key | Value | Notes |
+|---|---|---|
+| `security_list` | `[email protected]` | Inbound reports; **not** 
publicly archived (asked on adopt; with no dedicated list, request one from ASF 
Infra, and use `private@<project>.apache.org` only as a flagged fallback) |
+| `private_list` | `[email protected]` | PMC escalation; **not** 
publicly archived (auto-sourced default) |
+| `users_list` | `[email protected]` | Public advisories end up here; 
publicly archived (auto-sourced from `.asf.yaml` or default) |
+| `dev_list` | `[email protected]` | Release `[RESULT][VOTE]` threads; 
publicly archived (auto-sourced from `.asf.yaml` or default) |
+| `announce_list` | `[email protected]` | Cross-project announcement list; 
publicly archived |
+| `commits_list` | `[email protected]` | Publicly archived 
(auto-sourced from `.asf.yaml`) |
+
+Only URLs on publicly archived lists may appear in CVE `references[]` as
+`vendor-advisory`; see `../../AGENTS.md` and
+[`security-model.md`](security-model.md).
+
+The foundation-wide security forwarding address (e.g. `[email protected]`
+for ASF projects) is org-level — inherited from your organization's
+`security_inbox.foundation_security_address`. Do not declare it here.
+
+## Tools enabled
+
+| Capability | Tool | Adapter directory | Config knobs declared here |
+|---|---|---|---|
+| Issue tracking + project board | `github` | 
[`../../tools/github/`](../../../tools/github/) | `tracker_repo`, 
`upstream_repo`, `github_project_board_*`, `issue_template_fields` |
+| Security tracker backend | `github` (default), `local-files`, or `jira` — 
see [Tracker](#tracker) | 
[`../../tools/security-tracker/`](../../../tools/security-tracker/) (contract), 
[`tools/local-tracker/`](../../../tools/local-tracker/), 
[`tools/jira/`](../../../tools/jira/) | `tracker.platform`, `tracker.local.*`, 
`tracker.jira.*` |
+| Source control (VCS) | `github` (Git, default), or `svn` / `asf-svn` 
(Subversion) — see [Source control](#source-control); replaceable with another 
non-Git VCS | 
[`../../tools/github/source-control.md`](../../../tools/github/source-control.md),
 [`tools/asf-svn/source-control.md`](../../../tools/asf-svn/source-control.md), 
[`tools/vcs/`](../../../tools/vcs/) | `vcs_backend`, `upstream_repo`, 
`upstream_default_branch`; for `svn` also `svn_url`, `svn_repository_root`. On 
Subversion `secur [...]
+| Inbound email / drafts | `<one or more mail-source backends>` | 
[`../../tools/mail-source/contract.md`](../../../tools/mail-source/contract.md) 
(abstract) + per-backend adapter dirs (`tools/gmail/`, `tools/ponymail/`, 
`tools/mail-source/imap/`, `tools/mail-source/mbox/`, ...) | See [Mail 
sources](#mail-sources) below — declare each backend's role (primary / 
preferred-for-`<op>` / fallback / optional) and `mandatory` flag |
+| CVE allocation + record mgmt | *org-level* — inherited from 
`organizations/<org>/organization.md → cve_authority.tool`; for ASF: 
`vulnogram` 
([`tools/cve-tool-vulnogram/`](../../../tools/cve-tool-vulnogram/)), for 
independent: `mitre-form` | — | override in [CVE authority](#cve-authority) 
only if this project differs from its org |
+| Security cross-ref | `osv` | [`../../tools/osv/`](../../../tools/osv/) | 
`security_cross_ref.tool`, `security_cross_ref.ecosystem` |
+| Project metadata (rosters / people / releases) | *org-level* — inherited 
from `organizations/<org>/organization.md → project_metadata.kind`; for ASF: 
`apache-projects` 
([`tools/apache-projects/`](../../../tools/apache-projects/)), for independent: 
`none` | — | override in [Project metadata](#project-metadata) only if this 
project differs from its org |
+| Project chat | TODO: `slack`, `discord`, or `none` | 
[`../../tools/chat/`](../../../tools/chat/) (abstract) + adapter dirs 
(`tools/chat-slack/`, `tools/chat-discord/`) | `chat.kind`, `chat.channels`, 
`chat.guild_id` — see [Project chat](#project-chat) below; read-only, public 
channels only |
+| Release comms | TODO: the backend that carries release announcements — for 
ASF: `dev_list` / `announce_list` / `users_list`; for GitHub Releases leave 
blank | — | whichever release-comms keys the org default or per-project 
override declares |
+
+To replace a tool (e.g. swap GitHub issues for JIRA), declare an
+alternate tool in the table above, add a `tools/<name>/` adapter
+directory, and make sure the values the generic skills need are still
+reachable from this manifest.
+
+### Source control
+
+Which VCS the project's code lives in.
+A skill that runs [`magpie-vcs`](../../../tools/vcs/README.md) passes 
`vcs_backend` as `--backend`, so a checkout of the wrong kind fails loudly 
instead of silently using another backend.
+`/magpie-setup config` and `adopt` detect a Subversion-hosted project with 
`magpie-vcs probe` and propose these values; a Git project gets `git`.
+
+```yaml
+vcs_backend: git          # git | svn | hg | fossil; unset means git
+
+# Subversion only (vcs_backend: svn).
+svn_url: TODO             # project base URL, above trunk/branches/tags, e.g. 
https://svn.apache.org/repos/asf/foo
+svn_repository_root: TODO # repository root, e.g. 
https://svn.apache.org/repos/asf
+```
+
+With `vcs_backend: svn`:
+
+- `upstream_default_branch` is `trunk`, the line of work `magpie-vcs branch` 
reports.
+- The `svn` backend supports only the `trunk` / `branches/<name>` / 
`tags/<name>` layout below `svn_url`.
+  For a repository organised any other way, leave `upstream_default_branch` 
`TODO`: `branch` then reports the repository-relative path, and `new-branch` 
and name-based `switch` refuse.
+- `upstream_repo` names a GitHub repository only when the project really has 
one, such as a mirror it takes pull requests on.
+  Otherwise leave it `TODO`: the skills that act on GitHub pull requests and 
issues do not apply
+  (see [`tools/vcs/` → Subversion-hosted 
projects](../../../tools/vcs/README.md#subversion-hosted-projects)).
+
+## CVE tooling
+
+The CNA tool, allocation URL, record URL template, and allocation gate are
+**org-level** — inherited from your organization's `cve_authority` and
+`governance` blocks (see
+[`organizations/ASF/organization.md`](../../../organizations/ASF/organization.md)
+for ASF defaults,
+[`organizations/independent/organization.md`](../../../organizations/independent/organization.md)
+for the GitHub-native baseline). Override a key in the
+[Security workflow configuration → CVE authority](#cve-authority) block only
+if this project's CNA setup genuinely differs from its organization.
+
+The CNA's org UUID (`asf_org_id`, the `assignerOrgId` of every record) is
+org-level too: the ASF CNA uses one UUID for every Apache project, and the
+ASF organization supplies it.
+It is not needed to allocate a CVE; only the generated CVE JSON carries it.
+
+For **ASF adopters**, fill in the per-project CNA queue fields below:
+
+| Key | Value |
+|---|---|
+| `cna_private_owner` | TODO: e.g. `foo` (CNA_private.owner — the PMC's name 
in Vulnogram, the lower-case project slug) |
+| `cna_private_projecturl` | TODO: e.g. `https://foo.apache.org/` |
+| `cna_private_userslist` | TODO: e.g. `[email protected]` |
+
+## GitHub project board
+
+If the project uses a Projects V2 board for its security-issue view,
+declare the node IDs below. Fetch with the introspection query in
+[`../../tools/github/project-board.md`](../../../tools/github/project-board.md#introspection--re-fetch-the-option-ids).
+If the project does not run a board, leave the table blank — skills
+treat missing board config as *"no board reconciliation"*.
+
+| Key | Value |
+|---|---|
+| `project_board_url` | TODO |
+| `project_board_number` | TODO |
+| `project_board_node_id` | TODO |
+| `status_field_node_id` | TODO |
+
+**`Status` column → option-ID mapping** (re-fetch if any write
+returns `not found`):
+
+| Column | Option ID |
+|---|---|
+| `Needs triage` | TODO |
+| `Assessed` | TODO |
+| `CVE allocated` | TODO |
+| `PR created` | TODO |
+| `PR merged` | TODO |
+| `Fix released` | TODO |
+| `Announced` | TODO |
+
+## Project chat
+
+The contributor-growth skills read public chat channels for community signals, 
through the [`tools/chat/`](../../../tools/chat/) contract.
+Leave `kind: none` if the project has no public chat, or does not want it read.
+
+```yaml
+chat:
+  kind: none         # slack | discord | none
+  # guild_id: ""     # Discord only, optional: server (guild) ID when the bot 
joins several servers
+  channels: []       # channel names (Discord also accepts IDs) to read; empty 
= every public channel —
+                     # list them explicitly in a workspace shared by several 
projects
+```
+
+## Mail sources
+
+The skills treat every supported mail backend the same way —
+through the abstract operations defined in
+[`../../tools/mail-source/contract.md`](../../../tools/mail-source/contract.md).
+The adopter declares which backends are configured, what *role*
+each plays, and whether any are *mandatory*. The skill's resolution
+rule (see the contract) then picks the right backend per operation
+at run time.
+
+### Backend declaration
+
+One row per configured backend. **Exactly one** row carries
+`role: primary`. Multiple rows may carry `preferred for <op>` to
+override the primary for specific operations. `fallback` rows are
+tried in order when no preferred / primary backend supports the op.
+`mandatory: yes` means the skill **refuses to run** when that
+backend is unavailable; `no` means the skill continues with the
+remaining backends (and skips ops that no available backend supports).
+
+| Backend | Role | Mandatory | Notes |
+|---|---|---|---|
+| TODO: `gmail` | TODO: e.g. `primary` | TODO: `yes` / `no` | TODO: e.g. 
"Triager Gmail account subscribed to `<security-list>` and `<private-list>`" |
+| TODO: `ponymail` | TODO: e.g. `fallback` or `preferred for thread_url` | 
TODO: `yes` / `no` | TODO: e.g. "Read-only archive backstop; install per 
[`tools/ponymail/tool.md`](../../../tools/ponymail/tool.md)" |
+| TODO: *(add more rows as needed — `imap`, `mbox`, `mailman3`, 
project-specific adapter)* | | | |
+
+> **Mail backend selection is org-level.** The `mail_provider` block in
+> your organization manifest sets the primary and fallback backends
+> (for ASF: `primary: gmail-mcp`, `fallback: ponymail`; for independent:
+> `primary: none`, `fallback: none`). Only declare backends here that
+> override or extend what the organization manifest provides. For ASF
+> projects where PonyMail is the inherited fallback, declare it here only
+> to change its `mandatory` flag or role for this specific project; the
+> backend itself is already wired by the organization. Install PonyMail per
+> 
[`../../tools/ponymail/tool.md`](../../../tools/ponymail/tool.md#keeping-the-checkout-current).
+
+Reference adapter docs:
+[`tools/gmail/tool.md`](../../../tools/gmail/tool.md) (full read+write),
+[`tools/ponymail/tool.md`](../../../tools/ponymail/tool.md) (read-only ASF 
archive),
+[`tools/mail-source/imap/README.md`](../../../tools/mail-source/imap/README.md)
 (stub),
+[`tools/mail-source/mbox/README.md`](../../../tools/mail-source/mbox/README.md)
 (read-only offline archive — stub),
+[`tools/mail-source/mailman3/README.md`](../../../tools/mail-source/mailman3/README.md)
 (read-only public Mailman 3 / Hyperkitty archive).
+
+### Drafting backend
+
+Where the skills file the reply drafts they write.
+The project sets it here; a contributor overrides it for themselves with
+`tools.mail_create` in their own `user.md`.
+
+```yaml
+mail_create:
+  backend: gmail                          # gmail (default) or maildir
+  maildir:                                # only read when backend: maildir
+    drafts_path: ~/Mail/<project>/Drafts
+    from_address: TODO
+```
+
+`gmail` drafts in Gmail
+([`tools/gmail/draft-backends.md`](../../../tools/gmail/draft-backends.md));
+`maildir` files the draft into a local Maildir for Thunderbird or another
+mail client ([`tools/maildir/README.md`](../../../tools/maildir/README.md)).
+Resolution and the per-person override:
+[`draft-backends.md` § *How the skills pick a 
backend*](../../../tools/gmail/draft-backends.md#how-the-skills-pick-a-backend).
+
+### Per-backend config
+
+Per-backend values the generic recipes substitute in. Only fill in
+the rows for backends declared above; leave the rest blank or
+remove the row.
+
+| Key | Backend | Value |
+|---|---|---|
+| `security_list_domain` | `gmail` | TODO: e.g. `security.foo.apache.org` — 
Gmail `list:` operator uses the domain form |
+| `ponymail_private_search_url_template` | `ponymail` | TODO |
+| `ponymail_public_search_url_template` | `ponymail` | TODO |
+| `ponymail_api_url_template` | `ponymail` | TODO |
+| `ponymail_thread_url_template` | `ponymail` | 
`https://lists.apache.org/thread/<hash>?<list>` |
+| `imap_host` | `imap` | TODO: e.g. `imap.example.org` |
+| `imap_account` | `imap` | TODO: e.g. `[email protected]` |
+| `imap_security_list_folder` | `imap` | TODO: e.g. `INBOX.security-list` |
+| `imap_drafts_folder` | `imap` | TODO: e.g. `Drafts` (or leave blank to 
declare `create_draft` unsupported on this adapter) |
+| `mbox_archive_path` | `mbox` | TODO: e.g. 
`/srv/audit/security-list-2024.mbox` |
+| `mailman3_archive_url` | `mailman3` | TODO: e.g. 
`https://mail.example.org/archives` (the Hyperkitty root, without `/api`) |
+
+## Issue-template fields
+
+The skills' body-field roles map to the following concrete `###`
+headings in the project's issue template (the concrete YAML file lives in the
+adopter's `<upstream>` repo; the generic role → field contract is in The 
generic role → GitHub-field
+contract lives in
+[`../../tools/github/issue-template.md`](../../../tools/github/issue-template.md);
+the concrete names below are what skills read and write for this
+project.
+
+| Role (generic) | Field name | Template type | Required? |
+|---|---|---|---|
+| `issue-description` | TODO | `textarea` | TODO |
+| `public-summary` | TODO | `textarea` | TODO |
+| `affected-versions` | TODO | `input` | TODO |
+| `security-thread` | TODO | `input` | TODO |
+| `public-advisory-url` | TODO | `input` | TODO |
+| `reporter-credit` | TODO | `input` | TODO |
+| `pr-with-fix` | TODO | `input` | TODO |
+| `cwe` | TODO | `input` | TODO |
+| `severity` | TODO | `dropdown` | TODO |
+| `cve-tool-link` | TODO | `input` | TODO |
+
+## Security workflow configuration
+
+Skills resolve every workflow knob from the three-layer chain
+`project.md → organizations/<org>/organization.md → framework default`
+(see [`AGENTS.md` § Configuration resolution 
order](../../../AGENTS.md#configuration-resolution-order)).
+The **organization** you named under *Identity* supplies the org-wide
+defaults — the CNA tool, the governance gate, the mail / forwarder /
+archive backends, the project-metadata source, and the release-manager
+lookup cascade. For an ASF project these resolve to the Vulnogram /
+PonyMail / `apache-projects-mcp` / ASF-security values in
+[`organizations/ASF/organization.md`](../../../organizations/ASF/organization.md);
+`organization: independent` inherits the GitHub-native baseline in
+[`organizations/independent/organization.md`](../../../organizations/independent/organization.md).
+
+**Declare below only what is specific to this project.** Each block that
+is purely org-level says so and shows nothing — copy the matching key
+from the organization manifest down into that block only to override it
+(the project value wins). The blocks that every adopter fills in keep
+their per-project keys.
+
+### CVE authority
+
+Org-level — inherited from your organization's `cve_authority` block
+(CNA tool, allocate / record / source-tab URLs, state mapping,
+propagation, allocation-email flag, reviewer channel). Override a single
+key here only if this project's CNA setup differs from its organization.
+
+### Governance
+
+Org-level except the escalation contact: the allocation gate, gate
+label, release-vote gating, private governance list, and roster URL are
+inherited. Declare this project's escalation contact:
+
+```yaml
+governance:
+  # GitHub handle (or external contact) the skills cc / @-mention when
+  # escalating beyond the security team.
+  # Consumed by: security-issue-sync, pr-management-triage.
+  escalation_contact: "@<escalation-contact>"
+```
+
+### Security inbox
+
+Org-level except the concrete address: the inbox `kind`, the foundation
+security address, the `has_forwarder_relay` flag, the list filter, and
+the reporter-response timeout are inherited. Declare this project's
+inbound address:
+
+```yaml
+security_inbox:
+  # The concrete inbound address / channel ID / form URL for this project.
+  # Consumed by: security-issue-import, security-issue-sync, canned-responses.
+  address: <security-list>
+  # Optional override: addresses that send CVE-tool bookkeeping mail.
+  # ASF projects inherit [email protected]; if overriding this list, repeat
+  # that address and add the active CNA reviewers.
+  # Consumed by: security-issue-import's Step 1 pre-filter.
+  # cve_tool_senders: [[email protected], [email protected]]
+```
+
+**Optional override — `reporter_response_timeout_days`.** Days of
+reporter silence, counted from the security team's most recent outbound
+message on the reporter thread, before `security-issue-sync` proposes
+proceeding with the fix and announcement without further reporter
+sign-off. Per
+[ASF policy](https://www.apache.org/security/committers.html), an
+unresponsive reporter must not block the project team, particularly for
+a high-severity or high-impact issue. Your organization declares the
+default (14 days for both `ASF` and `independent`); add the key here only
+to depart from it — a project handling especially sensitive reports may
+want a longer window, one under heavy report volume a shorter one.
+Consumed by `security-issue-sync` (Step 1c staleness check / Step 2b
+proposal).
+
+```yaml
+security_inbox:
+  reporter_response_timeout_days: 21   # only if your project differs from its 
organization
+```
+
+### Forwarders
+
+Org-level — inherited from your organization's `forwarders` block (which
+relay adapters are enabled and their per-adapter detect / credit rules).
+Override here only to enable an extra relay this project uses.
+
+### Mail provider
+
+Org-level — inherited from your organization's `mail_provider` block
+(primary + fallback mail backends). Override here only if this project
+reads mail from a different backend than its organization.
+
+### Archive system
+
+Org-level — inherited from your organization's `archive_system` block
+(public-archive backend + URL templates). Override here only if this
+project's advisories surface on a different archive than its organization.
+
+### Project metadata
+
+Org-level — inherited from your organization's `project_metadata` block
+(roster / people / releases backend + whether it is mandatory). Override
+here only if this project uses a different metadata source.
+
+### Security cross-reference
+
+Vulnerability cross-referencing and alias lookup configuration (OSV.dev / NVD).
+Declare this project's default package ecosystem and tool adapter:
+
+```yaml
+security_cross_ref:
+  # Tool adapter: osv (tools/osv/) | none
+  tool: osv
+  # Default package ecosystem for vulnerability queries (e.g. PyPI, Maven, 
npm, Go, crates.io)
+  ecosystem: PyPI
+```
+
+### Tracker
+
+The tracker `board`, `visibility`, and `skill_url_template`
+are org-level defaults (`platform` defaults to `github`) — override them here 
only if this project differs
+(e.g. a project that runs its security tracker publicly sets
+`visibility: public`). Declare this project's per-tracker vocabulary:
+
+```yaml
+tracker:
+  # Where security reports live — the security-tracker contract
+  # (tools/security-tracker/contract.md). `github` (default): the private
+  # `tracker_repo`. `local-files`: markdown files in a folder of a private
+  # Git or SVN working copy (tools/local-tracker/). `jira`: a Jira project
+  # whose issues carry an issue-security level (tools/jira/).
+  # `/magpie-setup config` asks and, for local-files, learns the format of
+  # the reports already in the folder. `TODO` (not yet asked) reads as
+  # `github`; the question writes the confirmed choice here.
+  platform: TODO
+
+  # local-files only.
+  local:
+    root: TODO  # tracker folder, relative to the repository root, e.g. 
`security/reports`
+
+  # jira only.
+  jira:
+    url: TODO             # e.g. https://issues.example.org/jira
+    project: TODO         # project key, e.g. FOOSEC
+    security_level: TODO  # issue-security level every tracker must carry
+    issue_type: Bug
+    deployment: server    # server | cloud
+
+  # Whether the reporter can see the tracker issue once opened.
+  reporter_has_access: false
+
+  # Whether the tracker drives a board / kanban view.
+  project_board_enabled: true
+
+  # Body-field heading names — role -> the concrete `###` heading in this
+  # project's issue template. Skills refer to these by role.
+  # Consumed by: every skill that reads/writes the issue body.
+  body_fields:
+    cve_link: "CVE tool link"
+    mailing_thread: "Mailing list thread URL"
+    affected_versions: "Affected versions"
+
+  # Tracker labels — role -> the concrete label name in this project.
+  # Consumed by: security-issue-triage, security-issue-sync, 
pr-management-triage.
+  labels:
+    security_marker: "security"
+    needs_triage: "needs triage"
+    pr_open: "pr created"
+    pr_merged: "pr merged"
+    cve_allocated: "cve allocated"
+    not_cve_worthy: "not cve worthy"
+    # Label on the single open "rejected without tracker" ledger issue
+    # (see below). NOT the security_marker label.
+    rejections_ledger: "rejections-ledger"
+```
+
+#### Rejected-without-tracker ledger
+
+The `security-issue-import` skill sometimes rejects a report with a
+canned reply **without creating a tracker** (the disposition lives only
+on the mail thread). To keep those rejections countable, the team
+records each one as a comment on a single dedicated **ledger issue** in
+`tracker_repo`: one **open** issue, labelled with the
+`tracker.labels.rejections_ledger` value (default `rejections-ledger`)
+and **not** carrying the security-marker label.
+
+Adopters who want the *rejected without tracker* dashboard stat must:
+
+1. **Create the ledger issue** once in `tracker_repo` and label it
+   `rejections-ledger` (keep it open; the skills resolve it via
+   `gh issue list --repo <tracker> --state open --label
+   rejections-ledger`).
+2. **Set the dashboard knob.** Point
+   `security-tracker-stats.md → rejections_ledger_label` (or the
+   `rejections_ledger_label:` key in the renderer's YAML overlay) at the
+   same label. Set it to `null` to disable the stat — then no ledger
+   issue is needed.
+
+Each rejection comment carries a machine-parseable block
+(`<!-- rejection v1 -->` with `date:` / `reporter:` / `canned:` /
+`thread:` / `summary:` lines); a one-time historical backfill is a
+single `<!-- rejection-backfill v1 count: N -->` comment. The
+`security-tracker-stats-dashboard` renderer parses these and excludes the
+ledger issue from all tracker classification. Closes handled by
+`security-issue-invalidate` are **not** ledger entries.
+
+### Advisory records
+
+Optional, per-project — where the project records each published CVE in its 
own published security records
+(the site repository its security pages are built from),
+so that `security-issue-sync` can propose the change once cve.org shows the 
CVE published.
+Leave the block out and the step is skipped with a one-line note; the 
security-pages checklist reminder stays as it is.
+The deterministic part is `advisory-records` in
+[`tools/cve-tool-vulnogram/generate-cve-json/`](../../../tools/cve-tool-vulnogram/generate-cve-json/README.md#record-a-published-cve-in-the-projects-security-records--advisory-records);
+the step is described in 
[`docs/security/advisory-records.md`](../../../docs/security/advisory-records.md).
+
+```yaml
+advisory_records:
+  # git | svn. Default: the project's source-control backend (Tools enabled → 
Source control).
+  vcs: git
+  # Repository URL, used only to propose the first checkout.
+  repository: https://github.com/<org>/<project>-site.git
+  # Local working copy. A per-user path: `user.md → 
environment.advisory_records_clone` wins over this.
+  working_copy: ~/code/<project>-site
+  # Git only: the branch and remote the commit is pushed to.
+  branch: main
+  remote: origin
+  # One line; placeholder {cve_id}.
+  commit_message: "Add {cve_id} to the security pages"
+
+  # cve-json-file — one CVE 5.x JSON file per CVE, the record 
generate-cve-json emits
+  #                 (e.g. Apache HTTP Server keeps these under 
content/security/json/).
+  # release-page  — an entry in a per-release-line page, one section per fixed 
release, newest first
+  #                 (e.g. Apache Tomcat's xdocs/security-<line>.xml).
+  layout: cve-json-file
+
+  cve_json_file:
+    path: content/security/json/{cve_id}.json   # placeholders {cve_id}, {year}
+    indent: 4
+    keep_cna_private: false                     # drop the CNA tool's internal 
workflow block
+
+  release_page:
+    format: xml                                 # xml | markdown
+    path: xdocs/security-{line}.xml             # placeholder {line}
+    release_line_parts: 1                       # version components that name 
a line: 1 → "9" for 9.0.99
+    section_name: "Fixed in {product} {version}"
+    # Template files, relative to <project-config>; omit to use the shipped 
examples
+    # 
(tools/cve-tool-vulnogram/generate-cve-json/src/generate_cve_json/advisory_templates/).
+    # section_template: advisory-records/section.xml
+    # entry_template: advisory-records/entry.xml
+    # fix_commit_template: '<hashlink hash="{hash}"/>'
+    # section_parent: body                      # xml: where the first release 
section goes
+```
+
+### Scope detection
+
+Per-project — whether this project distinguishes scope sub-products, and
+the label → sub-product map:
+
+```yaml
+scope_detection:
+  # When false, every issue maps to the single product in the `product` block.
+  # Consumed by: security-issue-triage, generate-cve-json, security-issue-sync.
+  enabled: true
+
+  # Scope label -> sub-product: tracker label -> CVE product / packageName
+  # / upstream path-prefix the skill uses to confirm a PR touches that scope.
+  labels:
+    <scope-label>:
+      product: "<Product Name>"
+      packageName: "<package-name>"
+      path_prefix: "<path-prefix-regex>"
+    <secondary-scope-label>:
+      product: "<Secondary Product Name>"
+      packageName: "<secondary-package-name>"
+      path_prefix: "<secondary-path-prefix-regex>"
+```
+
+### Release process
+
+The release-manager lookup cascade and artifact registries are org-level
+and inherited. Declare this project's stale milestones and changelog
+fragment tool:
+
+```yaml
+release_process:
+  # Milestones the skills treat as "stale" (overdue for re-targeting) —
+  # exact milestone-name matches.
+  # Consumed by: security-issue-sync, pr-management-triage.
+  stale_milestones:
+    - "<stale-milestone-1>"
+    - "<stale-milestone-2>"
+
+  # Whether the upstream repo uses a changelog-fragment tool, and which one.
+  # Consumed by: security-issue-fix, issue-fix-workflow.
+  newsfragments:
+    enabled: true
+    tool: <fragment-tool>
+```
+
+### Roster
+
+The roster `source` is org-level and inherited. Declare this project's
+bare-name → handle map and release managers:
+
+```yaml
+roster:
+  # Mailing-list threads reference contributors by first name; this binds
+  # those to GitHub handles for @-mentions.
+  # Consumed by: security-issue-sync, pr-management-mentor.
+  bare_name_handles:
+    # Example (replace with your project's contributors):
+    "<FirstName>": "@<handle>"
+
+  # Release-manager handles, current first. Keep in sync with 
release-trains.md.
+  # Consumed by: security-issue-sync, security-issue-fix.
+  release_managers:
+    # Example (replace with your project's release managers):
+    - "@<handle>"
+```
+
+### Product
+
+Per-project — the product identity used in CVE records, advisories, and
+title normalization:
+
+```yaml
+product:
+  # Human-readable product name — lands in the CVE record's `product` field.
+  # Consumed by: generate-cve-json, canned-responses templating.
+  name: <ProjectShortName>
+
+  # Package-name shape for the primary artifact (PyPI / npm / Maven).
+  # Consumed by: generate-cve-json, canned-responses templating.
+  package_name: <package-name>
+
+  # Regex matched against changed paths in an upstream PR to confirm
+  # "this PR really touches the product" — a backstop in the fix flow.
+  # Consumed by: security-issue-fix, pr-management-triage.
+  code_pointer_path_prefix: "<code-path-prefix-regex>"
+
+  # Prefixes the title-normalization skill strips from an inbound subject
+  # when building a CVE title (matched at the start, case-insensitively).
+  # Consumed by: title-normalization, generate-cve-json, canned-responses.
+  subject_prefix_strip:
+    - "[SECURITY]"
+    - "[Security Report]"
+    - "Re:"
+    - "Fwd:"
+    - "<vendor>:"
+    - "<vendor> <product>:"
+
+  # Prefix the affected-versions extractor strips to leave the bare version.
+  # Consumed by: security-issue-sync, generate-cve-json.
+  affected_version_extract_prefix: "<ProjectShortName>"
+```
+
+## Pointers to sibling files
+
+- [`release-trains.md`](release-trains.md) — fast-moving release state, 
release-manager attribution, security-team roster.
+- [`milestones.md`](milestones.md) — milestone naming conventions.
+- [`scope-labels.md`](scope-labels.md) — scope label → CVE product mapping.
+- [`security-model.md`](security-model.md) — Security-Model URL + anchors.
+- [`title-normalization.md`](title-normalization.md) — CVE title strip cascade.
+- [`fix-workflow.md`](fix-workflow.md) — fork / toolchain / commit-trailer 
specifics.
+- [`naming-conventions.md`](naming-conventions.md) — project-specific 
editorial rules.
+- [`canned-responses.md`](canned-responses.md) — reporter-facing reply 
templates.
+- [`skill-sources.md`](skill-sources.md) — trusted external skill sources this 
project pulls skills from (the install gate).
+- [`README.md`](README.md) — project file index + onboarding checklist.
diff --git a/.apache-magpie-overrides/repo-health-config.md 
b/.apache-magpie-overrides/repo-health-config.md
new file mode 100644
index 0000000..9b97730
--- /dev/null
+++ b/.apache-magpie-overrides/repo-health-config.md
@@ -0,0 +1,191 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ -->
+
+<!-- START doctoc generated TOC please keep comment here to allow auto update 
-->
+<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
+**Table of Contents**  *generated with 
[DocToc](https://github.com/thlorenz/doctoc)*
+
+- [Repo-health audit configuration](#repo-health-audit-configuration)
+
+<!-- END doctoc generated TOC please keep comment here to allow auto update -->
+
+<!-- SPDX-License-Identifier: Apache-2.0
+     https://www.apache.org/licenses/LICENSE-2.0 -->
+
+# Repo-health audit configuration
+
+Per-skill switches for the repo-health audit family. Copy this file into
+your `<project-config>/` directory and fill in the `TODO` values. Skills
+in this family (`ci-runner-audit`, `workflow-security-audit`,
+`dependency-audit`, `license-compliance-audit`, `flaky-test-triage`, and
+`dependency-license-audit`) read from this file at run time.
+
+See `docs/repo-health/README.md` for a full description of each skill
+and adopter-contract details.
+
+---
+
+```yaml
+repo_health:
+
+  # ---------------------------------------------------------------------------
+  # ci-runner-audit — obsolete GitHub-hosted runner labels and macOS arch
+  # mismatches.  Consumed by: ci-runner-audit (experimental).
+  # ---------------------------------------------------------------------------
+  ci_runner_audit:
+
+    # Runner label names the skill treats as obsolete/retired.
+    # Default: the GitHub-deprecated label list below.
+    # Override when: your project uses custom runners whose labels should also
+    # be flagged (add them here), or you want to suppress a label from the
+    # default list (remove it).
+    deprecated_runner_labels:
+      - ubuntu-18.04
+      - ubuntu-20.04
+      - windows-2019
+      - macos-11
+      - macos-12
+
+    # Additional repositories to audit alongside the project's primary repos.
+    # Use `owner/repo` form. Leave empty to audit only the repos listed in
+    # project.md (upstream_repo, tracker_repo).
+    extra_repos: []
+
+  # ---------------------------------------------------------------------------
+  # workflow-security-audit — GitHub Actions security issues surfaced by
+  # zizmor.  Consumed by: workflow-security-audit (experimental).
+  # ---------------------------------------------------------------------------
+  workflow_security_audit:
+
+    # zizmor finding classes to enable. All four are on by default.
+    # Remove a class to suppress that finding category for this project.
+    # ASF default: all enabled (injection and fork-secrets are high-severity;
+    # excessive-permissions and unpinned-actions are medium-severity).
+    # Override when: the project intentionally uses floating action references
+    # (e.g. in non-production automation) or has a justified write permission.
+    enabled_rules:
+      - injection            # untrusted event data interpolated into run: 
steps
+      - excessive-permissions  # write-all or unneeded write scopes
+      - unpinned-actions     # @tag or @branch references instead of SHA pins
+      - fork-secrets         # secrets accessible from pull_request_target
+
+    # Additional repositories to audit beyond project.md → upstream_repo.
+    extra_repos: []
+
+  # ---------------------------------------------------------------------------
+  # dependency-audit — known-vulnerability check on direct + transitive deps.
+  # Consumed by: dependency-audit (experimental).
+  # ---------------------------------------------------------------------------
+  dependency_audit:
+
+    # Dependency managers in use. Selects the audit tool adapter.
+    # Allowed values: pip, npm, cargo, maven, gradle
+    managers:
+      - pip
+
+    # Minimum severity level to include in the report.
+    # Allowed values: low, medium, high, critical
+    # Default: medium (suppress low-signal informational hits).
+    min_severity: medium
+
+  # ---------------------------------------------------------------------------
+  # license-compliance-audit — SPDX header and NOTICE compliance check.
+  # Consumed by: license-compliance-audit (experimental).
+  # ---------------------------------------------------------------------------
+  license_compliance_audit:
+
+    # Required SPDX license expression for every source file under
+    # source_paths. Must be a valid SPDX expression string.
+    required_spdx_expression: "Apache-2.0"
+
+    # Source paths to audit for license headers (relative to upstream repo 
root).
+    source_paths:
+      - ".github/"
+      - "arm-docker-ami/"
+      - "github-runner-ami/"
+      - "lambdas/"
+      - "scripts/"
+      - "terraform/"
+      - "tests/"
+
+    # Paths to skip — test fixtures, vendored code, generated files, etc.
+    # The header templates themselves.
+    skip_paths:
+      - "license-templates/"
+
+  # ---------------------------------------------------------------------------
+  # flaky-test-triage — intermittent test failure detection from CI run 
history.
+  # Consumed by: flaky-test-triage (experimental).
+  # ---------------------------------------------------------------------------
+  flaky_test_triage:
+
+    # Audit window in days. The skill scans CI run history over this period.
+    # Default: 30 days (enough signal without fetching unbounded history).
+    window_days: 30
+
+    # Minimum failure-rate fraction to flag a job as candidate flaky.
+    # A job that fails 10% of the time or more is flagged by default.
+    # Override when: your project has a higher noise floor and 10% is too 
noisy.
+    failure_rate_threshold: 0.10
+
+    # Job-name glob patterns to include in the analysis.
+    # Leave empty to analyse all jobs in the CI run.
+    include_patterns: []
+
+    # Job-name glob patterns to exclude (known-always-failing or skipped jobs).
+    exclude_patterns: []
+
+  # ---------------------------------------------------------------------------
+  # dependency-license-audit — license classification of direct + transitive
+  # dependencies against a policy.  Consumed by: dependency-license-audit.
+  # ---------------------------------------------------------------------------
+  dependency_license_audit:
+
+    # License policy model.
+    #   asf       — apply the ASF three-category model (A allowed, B allowed
+    #               in binary/convenience-binary form only, X forbidden).
+    #   allowlist — allow only the SPDX expressions in allowed_licenses below.
+    # Default: asf.
+    policy: asf
+
+    # SPDX expressions always treated as allowed, regardless of policy.
+    # Override when: your project permits additional permissive licenses.
+    allowed_licenses:
+      - Apache-2.0
+      - MIT
+      - BSD-2-Clause
+      - BSD-3-Clause
+      - ISC
+
+    # SPDX expressions always treated as forbidden (ASF category X).
+    # Override when: your project has an exception for a specific dependency.
+    forbidden_licenses:
+      - GPL-2.0-only
+      - GPL-3.0-only
+      - AGPL-3.0-only
+      - LGPL-3.0-only
+
+    # Audit transitive dependencies, not just direct ones. Default: true.
+    include_transitive: true
+
+    # How to treat a dependency whose license cannot be resolved.
+    # Allowed values: flag (report as unknown), ignore.
+    # Default: flag.
+    unknown_license_action: flag
+```
diff --git a/.flake8 b/.apache-magpie.lock
similarity index 58%
rename from .flake8
rename to .apache-magpie.lock
index 6e7651c..88c68ae 100644
--- a/.flake8
+++ b/.apache-magpie.lock
@@ -14,7 +14,25 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-[flake8]
-max-line-length = 110
-ignore = E203,E231,E731,W504,I001,W503
-exclude = .svn,CVS,.bzr,.hg,.git,__pycache__,.eggs,*.egg
+
+# .apache-magpie.lock — committed; the project's floor.
+
+method:       marketplace
+url:          apache/magpie
+min_version:  0.9.0.dev202610250024
+
+plugins:
+  - magpie-setup
+  - magpie-utilities
+  - magpie-agent-guard
+  - magpie-vetted-ops
+  - magpie-repo-health
+
+reconciled:
+  version: 0.9.0.dev202610250024
+  at:      2026-10-25
+  skills:
+    dependency-audit:          sha256:19ba62ec34a55604
+    flaky-test-triage:         sha256:eda3c3891897f08d
+    license-compliance-audit:  sha256:b40b2993e5f18f54
+    workflow-security-audit:   sha256:e50eafff464d131a
diff --git a/.asf.yaml b/.asf.yaml
index 7cd4a1b..dd7aa9d 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 github:
   rulesets:
     - name: "Default Branch Protection"
diff --git a/.claude/settings.json b/.claude/settings.json
new file mode 100644
index 0000000..89da45c
--- /dev/null
+++ b/.claude/settings.json
@@ -0,0 +1,17 @@
+{
+  "enabledPlugins": {
+    "magpie-setup@apache-magpie": true,
+    "magpie-utilities@apache-magpie": true,
+    "magpie-agent-guard@apache-magpie": true,
+    "magpie-vetted-ops@apache-magpie": true,
+    "magpie-repo-health@apache-magpie": true
+  },
+  "extraKnownMarketplaces": {
+    "apache-magpie": {
+      "source": {
+        "source": "github",
+        "repo": "apache/magpie"
+      }
+    }
+  }
+}
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..ebc5af7
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,67 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+---
+# One grouped pull request per ecosystem and week. The cooldown keeps a 
release out until it has
+# been public for a week, so a compromised or yanked release is usually caught 
before it lands.
+version: 2
+updates:
+  - package-ecosystem: pre-commit
+    directory: /
+    schedule:
+      interval: weekly
+    cooldown:
+      default-days: 7
+    groups:
+      pre-commit:
+        patterns: ["*"]
+
+  - package-ecosystem: github-actions
+    directory: /
+    schedule:
+      interval: weekly
+    cooldown:
+      default-days: 7
+    groups:
+      github-actions:
+        patterns: ["*"]
+
+  - package-ecosystem: pip
+    directories:
+      - /
+      - /lambdas/scale_out_runner
+    schedule:
+      interval: weekly
+    cooldown:
+      default-days: 7
+    groups:
+      pip:
+        patterns: ["*"]
+
+  # Updates the providers in .terraform.lock.hcl and the version constraints 
in version.tf. A
+  # terraform/runs-on change is planned on its pull request and applied after 
merge, behind the
+  # runs-on-prod approval.
+  - package-ecosystem: terraform
+    directories:
+      - /terraform/runs-on
+      - /terraform/runs-on-access
+    schedule:
+      interval: weekly
+    cooldown:
+      default-days: 7
+    groups:
+      terraform:
+        patterns: ["*"]
diff --git a/.gitignore b/.gitignore
index ae24629..994f4d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 .cache
 __pycache__/
 .mypy_cache
@@ -46,3 +63,6 @@ session-manager-plugin.*
 # End of https://www.toptal.com/developers/gitignore/api/terraform
 github-runner-ami/packer/session-manager-plugin.deb
 github-runner-ami/packer/session-manager-plugin.rpm
+
+# Apache Magpie personal layer
+/.apache-magpie-local/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index fa32fe1..d0bacdc 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 ---
-default_stages: [commit, push]
+default_stages: [pre-commit, pre-push]
 default_language_version:
   # force all unspecified python hooks to run python3
   python: python3
@@ -26,12 +26,14 @@ repos:
       - id: identity
       - id: check-hooks-apply
   - repo: https://github.com/Lucas-C/pre-commit-hooks
-    rev: v1.1.9
+    rev: v1.5.6
     hooks:
       - id: forbid-tabs
       - id: insert-license
         name: Add license
-        exclude: ^\.github/.*$|^license-templates/|\.json$
+        # LICENSE is the license itself, lock files are generated, and 
cloud-init.yml must start with
+        # #cloud-config.
+        exclude: 
^\.github/.*$|^license-templates/|\.json$|\.md$|\.rst$|^LICENSE$|\.terraform\.lock\.hcl$|^cloud-init\.yml$
         args:
           - --comment-style
           - "|#|"
@@ -48,13 +50,23 @@ repos:
           - license-templates/LICENSE.rst
           - --fuzzy-match-generates-todo
         files: \.rst$
+      - id: insert-license
+        name: Add license for all Markdown files
+        exclude: ^\.github/.*$
+        args:
+          - --comment-style
+          - "<!--|| -->"
+          - --license-filepath
+          - license-templates/LICENSE.txt
+          - --fuzzy-match-generates-todo
+        files: \.md$
   - repo: https://github.com/psf/black
-    rev: 20.8b1
+    rev: 26.10.1
     hooks:
       - id: black
         args: [--config=./pyproject.toml]
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v3.4.0
+    rev: v6.0.0
     hooks:
       - id: check-merge-conflict
       - id: debug-statements
@@ -63,29 +75,26 @@ repos:
       - id: end-of-file-fixer
       - id: mixed-line-ending
       - id: trailing-whitespace
-      - id: fix-encoding-pragma
-        args:
-          - --remove
   - repo: https://github.com/asottile/pyupgrade
-    rev: v2.7.4
+    rev: v3.22.0
     hooks:
       - id: pyupgrade
         args: ["--py36-plus"]
   - repo: https://github.com/pre-commit/pygrep-hooks
-    rev: v1.7.0
+    rev: v1.10.0
     hooks:
       - id: rst-backticks
       - id: python-no-log-warn
-  - repo: https://github.com/timothycrosley/isort
-    rev: 5.7.0
+  - repo: https://github.com/PyCQA/isort
+    rev: 9.0.2
     hooks:
       - id: isort
         name: Run isort to sort imports
         files: \.py$
         # To keep consistent with the global isort skip config defined in 
setup.cfg
         exclude: ^build/.*$|^.tox/.*$|^venv/.*$
-  - repo: https://gitlab.com/pycqa/flake8
-    rev: 3.8.4
+  - repo: https://github.com/astral-sh/ruff-pre-commit
+    rev: v0.17.2
     hooks:
-      - id: flake8
-        name: Run flake8
+      - id: ruff-check
+        name: Run ruff
diff --git a/github-runner-ami/packer/files/runner-supervisor.py 
b/github-runner-ami/packer/files/runner-supervisor.py
index 6bc31d3..fe6e8e5 100755
--- a/github-runner-ami/packer/files/runner-supervisor.py
+++ b/github-runner-ami/packer/files/runner-supervisor.py
@@ -72,6 +72,7 @@ The order of operations is:
    then allow the termination lifecycle to continue
 
 """
+
 import ctypes
 import datetime
 import enum
@@ -614,7 +615,7 @@ class ProcessWatcher:
         check_call(['systemctl', 'stop', 'actions.runner', '--no-block'])
 
     def protect_from_scale_in(self, protect: bool = True):
-        """ Set (or unset) ProtectedFromScaleIn on our instance"""
+        """Set (or unset) ProtectedFromScaleIn on our instance"""
         if not OWN_ASG:
             # Not part of an ASG
             return
@@ -723,7 +724,7 @@ class ProcessWatcher:
         """
 
         class bpf_insn(ctypes.Structure):
-            """"The BPF instruction data structure"""
+            """The BPF instruction data structure"""
 
             _fields_ = [
                 ("code", ctypes.c_ushort),
@@ -733,7 +734,7 @@ class ProcessWatcher:
             ]
 
         class bpf_program(ctypes.Structure):
-            """"Structure for BIOCSETF"""
+            """Structure for BIOCSETF"""
 
             _fields_ = [("bf_len", ctypes.c_uint), ("bf_insns", 
ctypes.POINTER(bpf_insn))]
 
diff --git a/pyproject.toml b/pyproject.toml
index 0333bb0..76e05b9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -26,3 +26,11 @@ default_section = 'THIRDPARTY'
 # Need to be consistent with the exclude config defined in 
pre-commit-config.yaml
 skip = ['build','.tox','venv']
 profile = 'black'
+
+[tool.ruff]
+line-length = 110
+
+[tool.ruff.lint]
+# pycodestyle errors and warnings plus pyflakes, as flake8 ran them.
+select = ['E', 'W', 'F']
+ignore = ['E731']
diff --git a/requirements-test.txt b/requirements-test.txt
index 4e2748b..1dbcd4f 100644
--- a/requirements-test.txt
+++ b/requirements-test.txt
@@ -1,2 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 pytest~=6.0
 moto
diff --git a/scripts/list_committers b/scripts/list_committers
index e9697b4..d0b0d09 100755
--- a/scripts/list_committers
+++ b/scripts/list_committers
@@ -21,12 +21,17 @@ import rich_click as click
 from github import Github
 
 from rich.console import Console
+
 console = Console(color_system="standard", width=200)
 
+
 @click.command(short_help='List committer logins - used to sync list of 
committers in CI configuration')
[email protected]('--github-token', envvar='GITHUB_TOKEN',
-              help="You can generate the token with readOrg permissions: "
-                   
"https://github.com/settings/tokens/new?description=Read%20Org&scopes=read:org";)
[email protected](
+    '--github-token',
+    envvar='GITHUB_TOKEN',
+    help="You can generate the token with readOrg permissions: "
+    
"https://github.com/settings/tokens/new?description=Read%20Org&scopes=read:org";,
+)
 def main(github_token):
     gh = Github(github_token)
     org = gh.get_organization('apache')
@@ -37,7 +42,8 @@ def main(github_token):
     click.echo(" - update the `/runners/apache/airflow/configOverlay` 
parameter in AWS SSM ParameterStore")
     click.echo(" - restart the self-hosted runners")
     click.echo(
-        " - Inform the new committer, that it's time to open PR to update list 
of committers in dev/breeze/src/airflow_breeze/global_constants.py (COMMITTERS 
variable)"
+        " - Inform the new committer, that it's time to open PR to update list 
of committers in "
+        "dev/breeze/src/airflow_breeze/global_constants.py (COMMITTERS 
variable)"
     )
     click.echo(',\n'.join(committer_usernames))
     click.echo("""
@@ -53,7 +59,7 @@ AWS spot instances that are started on-demand.
 Those instances are way bigger than the Public Runners available for all ASF
 projects. They have 8 cores and 64 GB memory and all the builds happen
 in-memory, and our builds are optimized to use parallelism and memory so that
-often what you will get is 3-4 times speed-up vs the Public instances. 
+often what you will get is 3-4 times speed-up vs the Public instances.
 
 We currently have up to 35 such instances running at a time, so there is a
 possibility - if there are many committers pushing their changes in a short

Reply via email to