Motivation
Adding a filter today requires editing the same handful of central lists that every other filter PR also edits:
filters/src/lib.rs — a pub mod line and a pub use export
filters/src/register.rs — an entry in the shared use crate::{ ... } import block, a register_filters! call, and an entry in the build_ai_registry test's expected = [ ... ] array
Because these are append-heavy shared lists, any two in-flight filter PRs conflict by construction — not on filter logic, but on the registration bookkeeping. And the cost compounds with main's velocity: a filter PR that sits for a couple of weeks has to be rebased through the same 3-4 conflict points every time another filter merges.
Concretely, I hit this repeatedly rebasing three filter PRs (#709, #714, #769) onto a fast-moving main. Every rebase conflict was in register.rs/lib.rs/the test array — never in the actual filter. That's pure friction, and it scales with the number of contributors and the ~71 filters already registered.
This is a contributor-experience issue, not a correctness one — but for a project actively courting outside contributions, "every new filter conflicts with every other new filter" is exactly the kind of papercut worth removing early.
Idea (open to direction)
Move registration from a central list to self-registration, so a filter declares itself in its own module and there is no shared list to conflict on. A few options, in rough order of magic-vs-simplicity:
- Distributed slice (
inventory or linkme): each filter module does something like register_filter!("jwt_auth", JwtAuthFilter::from_config) locally; build_ai_registry() iterates the collected set. No central list; adding a filter touches only its own files.
- Per-category registration files: split the one big
register.rs into per-category modules so contention is at least spread out (partial mitigation, no new deps).
- Build-time codegen that discovers filter modules (heavier; probably not worth it).
The test's expected = [...] array could likewise be derived from the registry rather than hand-maintained.
Trade-offs I can see: inventory/linkme add a dependency and some indirection, and a central list is trivially greppable. But the conflict tax is real and only grows.
Ask
Is the team open to this direction (and if so, which flavor)? Happy to prototype option 1 behind a small PR if there's appetite. Even option 2 alone would meaningfully cut the contention.
Motivation
Adding a filter today requires editing the same handful of central lists that every other filter PR also edits:
filters/src/lib.rs— apub modline and apub useexportfilters/src/register.rs— an entry in the shareduse crate::{ ... }import block, aregister_filters!call, and an entry in thebuild_ai_registrytest'sexpected = [ ... ]arrayBecause these are append-heavy shared lists, any two in-flight filter PRs conflict by construction — not on filter logic, but on the registration bookkeeping. And the cost compounds with main's velocity: a filter PR that sits for a couple of weeks has to be rebased through the same 3-4 conflict points every time another filter merges.
Concretely, I hit this repeatedly rebasing three filter PRs (#709, #714, #769) onto a fast-moving main. Every rebase conflict was in
register.rs/lib.rs/the test array — never in the actual filter. That's pure friction, and it scales with the number of contributors and the ~71 filters already registered.This is a contributor-experience issue, not a correctness one — but for a project actively courting outside contributions, "every new filter conflicts with every other new filter" is exactly the kind of papercut worth removing early.
Idea (open to direction)
Move registration from a central list to self-registration, so a filter declares itself in its own module and there is no shared list to conflict on. A few options, in rough order of magic-vs-simplicity:
inventoryorlinkme): each filter module does something likeregister_filter!("jwt_auth", JwtAuthFilter::from_config)locally;build_ai_registry()iterates the collected set. No central list; adding a filter touches only its own files.register.rsinto per-category modules so contention is at least spread out (partial mitigation, no new deps).The test's
expected = [...]array could likewise be derived from the registry rather than hand-maintained.Trade-offs I can see:
inventory/linkmeadd a dependency and some indirection, and a central list is trivially greppable. But the conflict tax is real and only grows.Ask
Is the team open to this direction (and if so, which flavor)? Happy to prototype option 1 behind a small PR if there's appetite. Even option 2 alone would meaningfully cut the contention.