Airflow-Aware
Loaded by: repo-detect hook (SessionStart) when apache/airflow is detected in git remote or file structure.
Applies to: Any skill execution within an Apache Airflow contributor checkout — review, quick-fix, refactoring, or otherwise.
When to apply
A knowledge layer, not a review checklist, loaded by the
repo_detect hook when an Apache Airflow repo is detected (or via a memory entry with
triggers: [airflow-aware], see Memory-triggered skill loading).
Once loaded, treat every convention as background — do not re-read each task.
Layering: this skill sits on the Python language layer — read
python-aware first; this skill lists only what is Airflow-specific.
Precedence: the repo's AGENTS.md / CLAUDE.md > this skill > python-aware. A rule that changes a python-aware default is marked Airflow override.
Contributor conventions
1. Read AGENTS.md first — it wins
A condensed onramp, not a competing authority. Read AGENTS.md (or CLAUDE.md, identical) first; on conflict the repo file wins.
For review tasks also read .github/instructions/code-review.instructions.md.
2. Naming — Dag (prose) vs DAG (code)
In prose, write Dag (title case) — never all-caps DAG unless referring to the Python class, and never expand "Directed Acyclic Graph".
Code tokens stay as-is: class DAG, dag_id, airflow dags list, dag_processing/, DAG_FOLDER. See the "Naming" section of AGENTS.md.
The naming hook is a pure string match and false-positives on legitimate literals — classify each hit before "fixing" it (references/naming.md).
Never rewrite past entries in historical archival files (migrations-ref.rst, RELEASE_NOTES.rst / CHANGELOG.rst, provider changelog.rst); only new entries follow the rule.
3. Environment — Breeze + uv + prek
Airflow override: do not run pytest, mypy, or pre-commit on the host — use Breeze or uv run --project <sub-project> (the monorepo isolates dependencies per sub-project).
uv run --project airflow-core pytest tests/unit/foo/test_bar.py
uv run --project airflow-core ruff format src/
prek run --all-files # prek, not pre-commit: the runner upstream specifies
- Never use
--projectat the worktree root (full-workspace resolve →jpype1needs Java); a sub-project name is fine. - Reproduce a prek/CI hook failure from the repo root (only exception:
providers/, to dodge an unrelated lychee failure —references/verification-tooling.md§1). Scratch scripts go indev/. - Before trusting a
prek/pytest"Passed", local false reds,verify_completion/jpype1handling,uv.lockrebase handling:references/verification-tooling.md. - A
uv.lockdiff you did not cause is usually drift onmain— keep the re-lock out of a feature PR (references/review-checks.md, "uv.lock drift diagnostic").
4. Code style — Ruff + Mypy
Airflow override: line length 110 (not Ruff's 88 — agents most often miss this). New files need the Apache License header — copy it verbatim from an existing .py. Mypy runs via prek, not directly on the host.
5. Coding rules agents most often miss
- Do not add new
raise AirflowException— use a more specific exception class. sessionmust be keyword-only, and the callee must not callsession.commit(); transaction management is the caller's job.- Airflow-specific style (optional-extra import guard, naming, provider hooks, Dag authoring):
references/code-style.md; general Python style (imports, validation, mypy, docstrings):python-aware'scode-style.md. attrs eq/hash, serialize/decode, scoped-session gotchas:references/runtime-gotchas.md. General Python rules (noassert,time.monotonic(), import placement):python-aware. - A brand-new
provider.yamlmodule-section type trips a validator check — read the "New provider.yaml module section" recipe inreferences/registry-conventions.mdfirst.
6. Delivery completeness
A user-facing feature (new public class / SDK symbol / scheduling behaviour) ships all three in one PR: (1) implementation + tests; (2) an example Dag folded into an
existing example file, reusing its block style and objects — no new example file or bare new with DAG(...) block; (3) a docs update to the relevant .rst
(prose uses "Dag"; known limits are constraints, not # TODO). Adding or removing a public symbol also updates task-sdk/docs/api.rst and the airflow-core/docs/ autoapi entries
together with __init__.py / __all__ / the lazy-import table — both the removal and the addition. QA-plan and status-doc conventions: references/delivery.md.
7. Testing
- Airflow override: do not use
caplog— see the "Testing" section ofAGENTS.mdfor the prescribed pattern (typically a mock log handler asserted directly). - DB-touching tests must be marked
@pytest.mark.db_test. - Test paths mirror source paths:
airflow-core/src/airflow/foo/bar.py↔airflow-core/tests/unit/foo/test_bar.py. - pytest-only,
spec=/autospec=True, time-travel library, mock-assertion style:python-aware.
8. PR / commit / newsfragment
- Write commit messages and PR titles from the user-impact perspective, not which files were touched. Imminent fixes (obvious bugs, small refactors) can go straight to a PR.
- Before any commit message or PR text, load the repo's
airflow-pr-draft-summaryskill — it takes precedence overmaigo:commit-message(body states the why, subject ≤70 chars, not Conventional Commits, noCo-Authored-By). - Agent-opened PRs include a
Generated-by:footer (see the "Pull requests" section ofAGENTS.md). - Newsfragments are only required for changes to
airflow-core/,chart/, ordev/mypy/. - A docs-page PR attaches a before/after screenshot at PR-open time; never prefix a doc-only commit subject with
Docs:(it trips the conventional-commit hook) —references/delivery.md.
9. Architecture boundaries (optional, for architectural review)
Scheduler does not execute user code. Worker does not write to the metadata DB directly. Providers do not import from airflow core internals. Task SDK is isolated
from scheduler/worker internals. Cross-boundary changes need extra scrutiny — read code-review.instructions.md (its §1) first.
Core ↔ SDK paired classes (same name in airflow-core/ and task-sdk/): drift on a same-named attribute is a bug, not a nit — fix it in the current PR
(compare constructor signature, post-__init__ type, normalization, eager-raise; references/design-integrity.md).
10. Review-time-only checks (loaded as strict-review item 10+)
During a review task (🟡 Soyo running strict-review on an Airflow diff), read references/review-checks.md and append its sub-checks as items 10+, with the severity each states.
Its "Contents" list enumerates 10.1–10.37 plus the unnumbered DB portability and concurrency section. The file also holds the Airflow case studies backing strict-review's recurring must-fix patterns. Outside a review, skip the file.
11. CLI / REST / docs / backport conventions
- CLI and REST: grep sibling commands before designing a new semantic, filter or default; name a REST endpoint after the CLI's verb. Partitioned / scheduling-range APIs take
datetimebounds, notdate(references/design-integrity.md). - zh-TW locale content: say "Taiwanese Mandarin", never "Traditional Chinese" (commit messages, PR text, docs, comments); translation details in
references/ui-conventions.md. - Docs prose, status claims, user-facing snippets:
references/docs-conventions.md. A list already owned by another section defers to it —recurring-patterns.md. UI and backport judgment:references/ui-conventions.md,references/delivery.md.
References index
| Reference | Read when |
|---|---|
references/code-style.md |
Airflow-specific style: optional-extra import guard, naming (action verbs, AIP-21, private modules), provider hooks, maintainer preferences, core-symbol version-floor checks, Dag authoring |
references/runtime-gotchas.md |
attrs eq/hash, (de)serialization field reads, scoped-session lifecycle |
references/verification-tooling.md |
Before trusting a prek / pytest "Passed"; local false reds; attribution; docs screenshot procedure |
references/review-checks.md |
Review tasks: items 10+ (Contents at the top); uv.lock drift diagnostic |
references/registry-conventions.md |
A diff touches dev/registry/ or registry/, or adds a provider.yaml section |
references/design-integrity.md |
Hot-loop extension surfaces, Core ↔ SDK symmetry, CLI/REST consistency, range-API granularity |
references/docs-conventions.md |
Writing or reviewing docs prose, provider docs, docs examples |
references/test-cases.md |
Writing or reviewing Airflow tests: Airflow instances and Airflow-specific facts behind the python-aware test-conventions rules (read alongside the rule) |
references/ui-conventions.md |
airflow-core/src/airflow/ui changes; zh-TW translation rules |
references/naming.md |
The naming hook fires, or editing a historical archival file |
references/delivery.md |
Finishing a feature, QA / status docs, docs-page PRs, doc-only commit subjects, backports |
python-aware |
Always — the Python language layer this skill builds on |
hook-runner-verification.md |
Generic hook-runner false greens (stash, git add -N, rebase --continue, files: regex) |
strict-review/references/design-integrity.md |
Generic framework / base-API design rules (type-pairing guards, symmetric naming, sum-types) |
Composing with other skills
Builds on python-aware (Layering above); pairs with strict-review.
Review scenario — run strict-review's 9-item base checklist, then apply these as Airflow supplements: convention 2 (naming) → base item 4; 4 and 5 (style, correctness) → items 5–6;
6 (delivery completeness) → item 1; 7 (testing) → items 2–3. §10 sub-checks (10.1–10.37) become items 10+, with Block / Request-changes severity inherited from each sub-section.
Quick-fix / refactor scenario — use conventions 3–7 as background. Flag violations you notice, but do not run the full strict-review checklist unless the task calls for it; §10 is review-only.