TASK: Filter-scope audit — make "ema_crossover_v2 owns its filters" an
      ENFORCED property, not just today's state. Audit every registered
      filter's applies_to, pin the strategy→filter map with a test, and
      resolve the unregistered Revision-0 signal_quality module. Zero
      behaviour change.

## Established context

- Goal (Nitin, 2026-09-02): ema_crossover_v2's filters belong to it and are
  mapped to it; no strategy inherits another's filters; future filters
  (the Phase 2 context filter) land in the strategy's own set.
- The mechanism EXISTS: FilterManifest.applies_to (v2/filters/interface.py
  ~:61), honoured scope-BEFORE-check per Spec 02 §Invariants #2, enforced
  in v2/signal_engine/engine.py (~185-215) — with its own comment recording
  that regime_ci and m4_exhaustion once ran against every strategy and this
  was fixed. The dual-naming trap is documented in m4_exhaustion.py:52-62:
  manifests scope on the emitting strategy's MANIFEST NAME, and the
  production class declares "ema_crossover_v2" while the family name is
  "ema_crossover" — both are required in applies_to.
- Verified at HEAD 2026-09-02:
  trading_window {"*"} (platform clock, Spec §2.3);
  regime_ci, m4_exhaustion, signal_quality_v2 {"ema_crossover",
  "ema_crossover_v2"};
  signal_quality.py (Revision 0) {"ema_crossover"} ONLY — and
  api/v2_bootstrap registers SignalQualityV2Filter, apparently not the
  Revision-0 class.

## Verify the premises

1. The complete set of REGISTERED filters (api/v2_bootstrap and any other
   registration site) and each one's applies_to at HEAD — the table above
   re-verified, nothing missed (grep every FilterManifest construction).
2. Nothing anywhere registers or imports the Revision-0 signal_quality
   module (production, replay, shadow, experiments, tests). If something
   does, that importer changes this task's scope — STOP and report it.
3. Both evaluation paths honour applies_to: v2/pipeline.py::
   evaluate_filters AND signal_engine's evaluate_filters_ordered — confirm
   neither path can run a filter outside its declared scope.
4. What strategy manifest names exist today (the registry's all()) — the
   pin test must be written against the real names.

## OBJECTIVE

1. AUDIT: one table in the report — every registered filter, its
   applies_to, and one sentence on why that scope is deliberate
   (trading_window's "*" is ratified platform law; the other three are
   ema_crossover-family calibrations).
2. PIN: a test that asserts the exact strategy→filter mapping as a
   literal — every registered filter's (name, applies_to) — so any new
   filter or scope change must edit the test in the same change and is
   review-visible. The test also asserts the dual-naming rule: any filter
   scoped to the ema_crossover family names BOTH "ema_crossover" and
   "ema_crossover_v2" (the m4 trap, made unrepeatable), and that "*"
   appears ONLY on filters the audit table justifies as platform-wide.
3. RESOLVE Revision 0: if premise 2 confirms it is dead code, report the
   repo-convention disposition (retire with a dated note pointing at the
   superseding v2 module and its spec, or delete) — LIST the choice under
   G for Nitin's decision rather than deleting unilaterally; deletion is
   the operation an audit cannot undo. Do not fix its applies_to — a
   corrected manifest on an unregistered filter is polish on a module
   whose status is the actual question.
4. One paragraph in the filter interface's docstring (or the pipeline's
   FILTER_ORDER comment — wherever a filter author will actually look)
   stating the going-forward rule: new filters declare explicit strategy
   names; {"*"} requires the audit table's justification and the pin
   test's edit.

## Do NOT change

Any filter's logic, order, or SCOPE — zero admitted/refused deltas; if the
audit finds a scope that looks WRONG, that is a G-item for Nitin, not an
inline fix · FILTER_ORDER · the strategy modules · specs (the pin test
enforces; no spec amendment is needed for a test).

## Tests

The pin test itself, green against HEAD. Then the FULL suite:

    bash backend/scripts/ci/run_all.sh

All 13 gates green.

## Verification report

A. The audit table (filter, applies_to, justification)  B. Premise-2
verdict on Revision 0 (importers found: none/list)  C. Both-paths scope
enforcement proof  D. The pin test (what it asserts, literally)
E. 13 gates  F. Premises that did not match  G. Decisions for Nitin
(Revision-0 disposition; any scope that looks wrong)  H. Unknowns

CRITICAL: This task changes no behaviour — it converts a true fact into an
enforced one. If any premise reveals a filter running out of scope TODAY,
that is a live defect: STOP and report it before pinning anything.
