SIGN IN SIGN UP

ci: fail safe when a changed file matches no known CI path filter (#2010)

* ci: fail safe when a changed file matches no known CI path filter

merge-gate.ts treats every "skipped" required job as fine — it never
asks whether the skip was actually justified by the diff. #2009 closed
the one known instance of this (rust-toolchain.toml not classified as
a Rust change), but the underlying mechanism is generic: any file this
workflow's paths-filter has not been taught about silently skips every
Rust and frontend job, and Merge Gate still goes green.

Add a catch-all `unclassified` filter ('**' minus every pattern already
used by another filter) and OR its output into every change-gated job's
`if:`. An unrecognized file now forces the full matrix to run instead of
silently skipping, closing the general class of bug behind #2003/#2008,
not just the specific file that triggered it.

This does mean a PR that only touches something outside every named
filter (e.g. a new root config file, LICENSE, docs/**) now runs full CI
instead of skipping everything, trading some CI minutes for not being
able to merge an uncompiled toolchain/dependency change again.

check-core-tauri-integration's inverted fast-path condition is left
alone: it is a redundant optimization for the "core changed, tauri did
not" case, not a required safety net — lint-core/lint-tauri/test-build
already cover unclassified changes on their own.

* ci: make the unclassified catch-all honor its exclusions

The catch-all filter was added to the existing paths-filter step, which
runs with the action's default predicate-quantifier 'some' ("file is
included if it matches at least one pattern"). Under those semantics the
leading '**' matches every changed file on its own and the '!' rules can
never take it back, so `unclassified` evaluated to true for every PR --
running the full matrix always, instead of only for genuinely
unclassified files.

Move the catch-all into its own paths-filter step using
'some-with-excludes' ("matches at least one positive pattern and no
negated one"). predicate-quantifier is step-scoped and the other filters
rely on the default 'some', so they cannot share a step.

Also switch the change-detection barrier from `wait: changes` to
`wait-all: true` so the new background step is awaited too.

Verified against a transcription of filter.ts at the pinned action SHA:
27 representative paths, 18 wrong under 'some', all correct under
'some-with-excludes'.

Reported by CodeRabbit and Codex.
S
shm committed
f69dd4dcedbb4305413e932256055e5dfa2f7fc3
Parent: 073f79f
Committed by GitHub <noreply@github.com> on 8/24/2026, 11:53:12 PM