Audit: Expensive lane path filtering¶
What we check¶
Ephemeral VM runners (the vm label) are the expensive pool: the
lanes that run on them build entire clouds or boot guests, and a
single run costs tens of minutes to hours of capacity. A pull
request or merge queue entry that touches only content no lane
exercises should not pay for them. The content in question is the
docs/ directory (where one exists) and the review-tracking state
(REVIEWS.md and the .vscode weaudit files, where review
tracking is deployed).
Every workflow that runs vm-runner jobs on pull_request or
merge_group must therefore be path-filtered, and the filter must
exclude the repository's non-code content: a docs/** pattern
where the repository has a docs/ directory, and a REVIEWS.md
pattern where it carries .vscode/review-scope.toml.
Two filtering mechanisms count:
- A workflow backing no required status check may use trigger-level
paths:/paths-ignore:. An inclusion-stylepaths:list (naming what the lane exercises, as the rust workflows do) excludes everything else by construction and passes without pattern checks. - A workflow backing a required status check must use a filter job
instead —
dorny/paths-filterfeeding job-levelif:conditions, as kerbside'scheck_pathsjobs do. Trigger-level filtering cannot coexist with required checks: a required check in apaths-ignore'd workflow never reports on a filtered PR, and a required check that never reports blocks the merge forever, while a skipped one satisfies it.
The worked example is kerbside: functional-tests.yml,
direct-qemu-functional.yml, and sf-e2e-functional.yml each
carry a check_paths filter job, functional-tests.yml also runs
its filter on merge_group so a docs-only or review-marks-only
queue entry skips the cloud matrices, and
kerbside's docs/testing.md
documents the design. When adopting the pattern, note
dorny/paths-filter's predicate-quantifier: 'every' trap: the
default ANY-match semantics make a '**' pattern defeat every
exclusion.
Dedicated content-scanner workflows (gitleaks, trufflehog,
detect-secrets) are exempt. Their whole point is to read the
human-written text a filter would skip: a secret lands in docs or
review marks as easily as in code. This is the same reasoning that
keeps content scanners out of paths-ignore in the review-tracking
adoption procedure (see
workflow-standards.md).
Dedicated is measured per job: every job in the workflow must
invoke a scanner, outside of comments. The argument for the
exemption is about the scanner job, not about the file it happens to
live in, so it only carries a whole workflow when the whole workflow
is the scanner. Asking merely whether a scanner appeared anywhere in
the file gave shakenfist/actions a pass for a ci.yml that ran
lint, unit tests and the LLM reviewer on ephemeral VMs for every
documentation typo, on the strength of the gitleaks job sitting
beside them.
A mixed workflow is therefore held to the exclusion requirements
whether or not it already carries a filter, and its scanner jobs
should simply not consume the filter's output. Ryll's ci.yml is
the worked example of the shape, and currently of the mistake too:
its gitleaks job carries the same check_paths condition as the
expensive lanes, so ryll's secret scan skips documentation-only
pull requests.
Other deliberate exceptions — a lane that must run even for
docs-only changes — are marked with an audit-ok: no-path-filter
comment anywhere in the workflow file, ideally with a reason.
Repositories with neither a docs/ directory nor review tracking
have nothing for a filter to exclude and are reported as not
applicable, as are repositories whose PR-triggered workflows never
use vm runners.
Template¶
No template — the correct shape depends on whether the workflow
backs a required status check. Copy the check_paths pattern from
kerbside's smoke workflows for gating lanes, or add trigger-level
paths-ignore for advisory ones.
Projects¶
This table is regenerated daily by the consistency audit
workflow from scripts/audit-check.py results; do not edit
it by hand.
Last regenerated: 2026-08-23T06:45:38.740880+00:00
| Project | Status | Issue |
|---|---|---|
| actions | compliant | - |
| agent-python | non-compliant | agent-python#123 |
| client-python | compliant | - |
| client-python-k3s | non-compliant | client-python-k3s#29 |
| clingwrap | non-compliant | clingwrap#118 |
| cloudgood | N/A | - |
| development | compliant | - |
| divergulent | compliant | - |
| instar | compliant | - |
| kerbside | compliant | - |
| kerbside-patches | compliant | - |
| library-utilities | compliant | - |
| occystrap | non-compliant | occystrap#113 |
| private-ci | N/A | - |
| ryll | compliant | - |
| sfui | non-compliant | sfui#14 |
| shakenfist | compliant | - |
Details for non-compliant projects:
- agent-python (Status): 1 expensive lane(s) triggered by pull_request or merge_group without adequate path filtering: functional-tests.yml (no path filtering). Add a check_paths filter job (see kerbside functional-tests.yml) or, only for workflows backing no required status check, trigger-level paths-ignore, excluding docs/** and the review-tracking files; mark deliberate exceptions with an "audit-ok: no-path-filter" comment
- client-python-k3s (Status): 1 expensive lane(s) triggered by pull_request or merge_group without adequate path filtering: functional-tests.yml (no path filtering). Add a check_paths filter job (see kerbside functional-tests.yml) or, only for workflows backing no required status check, trigger-level paths-ignore, excluding docs/** and the review-tracking files; mark deliberate exceptions with an "audit-ok: no-path-filter" comment
- clingwrap (Status): 1 expensive lane(s) triggered by pull_request or merge_group without adequate path filtering: functional-tests.yml (no path filtering). Add a check_paths filter job (see kerbside functional-tests.yml) or, only for workflows backing no required status check, trigger-level paths-ignore, excluding docs/** and the review-tracking files; mark deliberate exceptions with an "audit-ok: no-path-filter" comment
- occystrap (Status): 2 expensive lane(s) triggered by pull_request or merge_group without adequate path filtering: functional-tests.yml (no path filtering), python-unit-tests.yml (no path filtering). Add a check_paths filter job (see kerbside functional-tests.yml) or, only for workflows backing no required status check, trigger-level paths-ignore, excluding docs/** and the review-tracking files; mark deliberate exceptions with an "audit-ok: no-path-filter" comment
- sfui (Status): 1 expensive lane(s) triggered by pull_request or merge_group without adequate path filtering: functional-tests.yml (no path filtering). Add a check_paths filter job (see kerbside functional-tests.yml) or, only for workflows backing no required status check, trigger-level paths-ignore, excluding docs/** and the review-tracking files; mark deliberate exceptions with an "audit-ok: no-path-filter" comment