Files
Palash DebnathandClaude Opus 5 92b1ee5d1b test(asr): parse the selector guard instead of grepping it (#1524)
* test(asr): parse the guard, don't grep it

Two Majors CodeRabbit raised on #1523 — which I merged before reading
them, so this is the follow-up rather than a fix on the branch.

- Approved files were matched by BASENAME, so any future
  `<anything>/asr_backend.py` was exempt from the guard it exists to
  enforce. Matching is by relative path now; a decoy
  `backend/engines/asr_backend.py` calling the selector is caught.
- Detection was a line regex, wrong in both directions: it missed
  `import get_active_asr_backend as pick` and fired on the name inside
  docstrings and comments. It walks the AST now, alias-aware, so only
  real calls count.

Both verified by planting the exact bypasses: an aliased call in
services/tts_backend.py and the decoy module above. Neither was caught
before this change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(asr): resolve the selector's bindings before flagging a call

CodeRabbit, #1524: matching any call named get_active_asr_backend also
reported a local helper or an unrelated object's method that happens to
share the name. False positives are how a guard stops being believed —
people add allowlist entries for code that was never the bug.

Bindings are resolved first now: a bare call counts only if the name was
imported FROM services.asr_backend, an attribute call only if it hangs
off a module alias for it. Six shapes are pinned in the suite — direct,
aliased and module-attribute calls flagged; a same-named local function,
an unrelated method, and the name inside a docstring not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 01:40:01 +00:00
..