This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow-steward.git
The following commit(s) were added to refs/heads/main by this push:
new ba104c4 add License headers rule body: defer to header tooling, cover
the no-tooling and exclusion-masking cases (#195)
ba104c4 is described below
commit ba104c438ae78bc2fc2f65e3fe020d16b2dd2a3f
Author: Paul King <[email protected]>
AuthorDate: Mon May 18 01:23:48 2026 +1000
add License headers rule body: defer to header tooling, cover the
no-tooling and exclusion-masking cases (#195)
PR #187 added "License headers" to the canonical category list and
a section-anchor URL, but no rule body — making it the only
framework-default category with neither an adopter source nor a
criteria.md section. This adds the missing `## License headers`
section so it matches its siblings (Third-party license compliance,
Security model, Quality signals).
The section is written as a deference-plus-judgement layer, not a
re-implementation of apache-rat / pre-commit:
- When a header check is in the status-check rollup, that tool is
authoritative for mechanical presence/absence; Golden rule 8 +
the CI precheck already block approve on its failure. The skill
does not raise a duplicate "missing header" finding, and treats
the project's tool config (not the policy page) as the source of
truth for scope/exclusions.
- Projects with no header tooling: the skill is the safety net and
scans added/rewritten source files itself.
- Exclusion-masking case: when the same PR both adds a header-tool
exclusion entry and a file lacking an Apache header, CI passes
green by construction and deference gives no coverage — the skill
raises a finding asking the maintainer to confirm the exclusion
is appropriate.
- Judgement cases the tool cannot decide (mis-applied SPDX, wrong
license, third-party header routing) are called out, closing the
loop with the existing Third-party-license-compliance cross-ref.
Generated-By: Claude Opus 4.7 (1M context) <[email protected]>
---
.../skills/pr-management-code-review/criteria.md | 100 ++++++++++++++++++++-
1 file changed, 99 insertions(+), 1 deletion(-)
diff --git a/.claude/skills/pr-management-code-review/criteria.md
b/.claude/skills/pr-management-code-review/criteria.md
index c11ea53..4d58b47 100644
--- a/.claude/skills/pr-management-code-review/criteria.md
+++ b/.claude/skills/pr-management-code-review/criteria.md
@@ -100,7 +100,8 @@ inclusion is correctly attributed and no finding is raised.
**Relationship to "License headers":** when a new file's header is non-Apache
but not third-party (e.g. a contributor accidentally used the wrong SPDX
-identifier), the "License headers" finding applies. When the header is
+identifier), the "License headers" finding applies (see
+[§ License headers](#license-headers) below). When the header is
clearly from an upstream library or external author, route to this category
instead — the fix is to preserve the original header and update `LICENSE`,
not to replace it with an Apache header.
@@ -110,6 +111,103 @@ Source: `https://www.apache.org/legal/resolved.html` and
---
+## License headers
+
+ASF policy requires every source file in a release to carry the
+standard Apache license header
+(`https://www.apache.org/legal/src-headers.html`). This is a
+**framework-level default** that applies regardless of
+adopter-specific rules.
+
+**Defer to the project's header tooling when it exists.** Most ASF
+projects enforce headers in CI — `apache-rat`, the pre-commit
+`insert-license` hook, `license-eye` / `skywalking-eyes`, or an
+equivalent. If such a check appears in the PR's status-check
+rollup (the [CI precheck](prerequisites.md) already reads it):
+
+- That tool is **authoritative for the mechanical question** —
+ "does this file carry the header" — including which paths are
+ in scope. Do **not** raise a duplicate "missing header"
+ finding: a real miss already turns the check red, and Golden
+ rule 8 already takes `APPROVE` off the table and quotes the
+ failing check. Restating it as a review finding is noise and
+ risks contradicting the tool's own exclusion list.
+- The source of truth for **scope and exemptions** is the
+ project's tool config (the `apache-rat` `<excludes>` block,
+ `.rat-excludes`, the pre-commit `exclude:` regex, the
+ `licenserc.yaml` ignore globs — whatever the project uses),
+ **not** the policy page. When reasoning about whether a file
+ is in scope, read that config, not a summarised list here.
+
+**Fallback — projects with no header tooling.** If no
+license-header check appears in the rollup, the skill **is** the
+safety net. Scan every source file the diff **adds** (and any it
+materially rewrites) for the Apache header; raise a `major`
+finding for each contributor-authored file missing it, quoting
+`https://www.apache.org/legal/src-headers.html`. Apply the
+exemptions below using judgement, and the *When in doubt — defer*
+rule at the end of this file for anything borderline.
+
+**The exclusion-masking case — check even when CI is green.**
+Deference above assumes the tool's exclusion list is fixed. It is
+not when the **PR itself changes it**. If the same diff both
+(a) adds or modifies a header-tool exclusion entry — an
+`<exclude>` in `pom.xml` / `build.gradle`, a line in
+`.rat-excludes`, an `exclude:` pattern in
+`.pre-commit-config.yaml`, an ignore glob in `licenserc.yaml`,
+etc. — and (b) adds a file that lacks an Apache header or carries
+a third-party header, then the check passes **green by
+construction** and CI deference gives no coverage. This is
+precisely where the skill earns its place. Raise a `major`
+finding asking the maintainer to confirm the exclusion is
+appropriate:
+
+- **Legitimately exempt** — generated code, data/test fixtures,
+ binary assets, or a genuinely third-party file correctly
+ attributed in `LICENSE` (route the third-party part to
+ [§ Third-party license compliance](#third-party-license-compliance)).
+ If so, the exclusion is fine; note it and move on.
+- **Masking a missing header** — a contributor-authored source
+ file that simply has no header and was excluded to make CI
+ pass. Not acceptable; the fix is to add the header, not to
+ exclude the file.
+
+Quote the added exclusion line and the offending file path in the
+finding so the maintainer can adjudicate without digging.
+
+**Judgement cases the tool cannot decide.** Even on a
+fully-tooled project, raise a finding for:
+
+- a contributor-authored file with a **mis-applied SPDX
+ identifier** or the **wrong license** in an otherwise
+ Apache-intended header (the tool sees *a* header and passes;
+ the header is still wrong);
+- a header that is **clearly third-party / upstream** — do not
+ treat as a missing-header miss; route to
+ [§ Third-party license compliance](#third-party-license-compliance)
+ (the fix there is preserve-and-attribute, not replace).
+
+**Exemptions (no finding).** Generated files; vendored or
+third-party files (handled by the third-party category); data and
+test-resource fixtures; binary files; trivially short config/data
+files where the project conventionally omits headers. On a tooled
+project the project config is the authority for these; on an
+untooled project use judgement and defer when unsure.
+
+| Situation | Severity |
+|---|---|
+| Missing header, no header tooling in CI | `major` |
+| Missing / 3rd-party header + new tool exclusion in same PR | `major`
(confirm exclusion is justified) |
+| Wrong / mis-applied SPDX on contributor-authored file | `major` |
+| Missing header but header tooling is red on the PR | no separate finding —
defer to CI (Golden rule 8) |
+| Header added in this PR alongside the file | `nit` / no finding |
+
+Source: `https://www.apache.org/legal/src-headers.html` (policy)
+and the project's own header-tool configuration (scope and
+exemptions).
+
+---
+
## Per-area / subtree-specific signals
When a PR touches a subtree the adopter listed in