| applyTo | ** |
|---|---|
| excludeAgent | coding-agent |
Use these rules when reviewing pull requests to the Apache Airflow repository.
- Scheduler must never run user code. It only processes serialized Dags. Flag any scheduler-path code that deserializes or executes Dag/task code.
- Flag any task execution code that accesses the metadata DB directly instead of through the Execution API (
/executionendpoints). - Flag any code in Dag Processor or Triggerer that breaks process isolation — these components run user code in isolated processes.
- Flag any provider importing core internals like
SUPERVISOR_COMMSor task-runner plumbing. Providers interact through the public SDK and execution API only.
- Flag any SQLAlchemy relationship access inside a loop without
joinedload()orselectinload()— this is an N+1 query. - Flag any query on
run_idwithoutdag_id.run_idis only unique per Dag. Queries that filter, group, partition, or join onrun_idalone will silently collide across Dags. - Flag any
session.commit()call inairflow-corecode that receives asessionparameter. Session lifecycle is managed by the caller, not the callee. - Flag any
sessionparameter that is not keyword-only (*, session) inairflow-core. - Flag any database-specific SQL (e.g.,
LATERALjoins, PostgreSQL-only functions, MySQL-only syntax) without cross-DB handling. SQL must work on PostgreSQL, MySQL, and SQLite.
- Flag any
assertin non-test code.assertis stripped in optimized Python (python -O), making it a silent no-op in production. - Flag any
time.time()used for measuring durations. Usetime.monotonic()instead —time.time()is affected by system clock adjustments. - Flag any
fromorimportstatement inside a function or method body. Imports must be at the top of the file. The only valid exceptions are: (1) circular import avoidance, (2) lazy loading for worker isolation, (3)TYPE_CHECKINGblocks. If the import is inside a function, ask the author to justify why it cannot be at module level. - Flag any
@lru_cache(maxsize=None). This creates an unbounded cache — every unique argument set is cached forever. Note:@lru_cache()without arguments defaults tomaxsize=128and is fine. - Flag any heavy import (e.g.,
kubernetes.client) in multi-process code paths that is not behind aTYPE_CHECKINGguard. - Flag any file, connection, or session opened without a context manager or
try/finally.
- Flag any new public method or behavior without corresponding tests. Tests must cover success, failure, and edge cases.
- Flag any
unittest.TestCasesubclass. Use pytest patterns instead. - Flag any
mock.Mock()ormock.MagicMock()withoutspecorautospec. Unspec'd mocks silently accept any attribute access, hiding real bugs. - Flag any
time.sleepordatetime.now()in tests. Usetime_machinefor time-dependent tests. - Flag any issue number in test docstrings (e.g.,
"""Fix for #12345""") — test names should describe behavior, not track tickets.
- Flag any query on mapped task instances that does not filter on
map_index. Without it, queries may return arbitrary instances from the mapped set. - Flag any Execution API change without a Cadwyn version migration (CalVer format).
- Avoid
useState + useEffectto sync derived state. Use nullish coalescing or nullable override patterns instead. - Extract shared logic into custom hooks rather than copy-pasting across components.
- Flag any manual edits to files in
openapi-gen/or Task SDK generated models. These must be regenerated, not hand-edited.
Flag these patterns that indicate low-quality AI-generated contributions:
- Fabricated diffs: Changes to files or code paths that don't exist in the repository.
- Unrelated files included: Changes to files that have nothing to do with the stated purpose of the PR.
- Description doesn't match code: PR description describes something different from what the code actually does.
- No evidence of testing: Claims of fixes without test evidence, or author admitting they cannot run the test suite.
- Over-engineered solutions: Adding caching layers, complex locking, or benchmark scripts for problems that don't exist or are misunderstood.
- Narrating comments: Comments that restate what the next line does (e.g.,
# Add the item to the listbeforelist.append(item)). - Empty PR descriptions: PRs with just the template filled in and no actual description of the changes.
- For bug-fix PRs, flag if there is no regression test — a test that fails without the fix and passes with it.
- Flag any existing test modified to accommodate new behavior — this may indicate a behavioral regression rather than a genuine fix.