fix(test): watermark producer scan must match code, not prose (#1564)

* fix(test): watermark producer scan must match code, not prose

ee35d238 broke main's CI by adding a comment that *mentions*
backend.generate() to worker/transport/server.py — the watermark coverage
guard greps raw source, so the comment made the module a 'producer' that
never marks. Blank COMMENT/STRING token spans before matching (layout
preserved, unparseable files fall back to a raw scan) and apply the same
rule to the allowlist staleness check; a new self-test pins the class.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(test): keep f-string code scannable; require code-level mark_synthetic

Greptile P1 + CodeRabbit on #1564: on Python <=3.11 an entire f-string is
one STRING token, so blanking it would let a synthesis call inside a
replacement field evade the producer scan — f-prefixed strings now stay
raw there (fail closed), while 3.12+ blanks only literal FSTRING_MIDDLE
text. The 'module references mark_synthetic' certification is now also
code-only, so a comment can't satisfy it. Self-test extended with both.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Palash Debnath
2026-08-16 15:44:58 +00:00
committed by GitHub
co-authored by Claude Fable 5
parent ee35d2389e
commit 4db02d0c97
+70 -4
View File
@@ -21,7 +21,9 @@ tests/test_synthetic_audio_watermark_1169.py.
"""
from __future__ import annotations
import io
import re
import tokenize
from pathlib import Path
import pytest
@@ -75,6 +77,46 @@ _PRODUCERS = [
]
def _code_only(src: str) -> str:
"""``src`` with comments and string literals blanked to spaces.
ee35d238 made a module a "producer" by *mentioning* ``backend.generate()``
in a comment — prose can't synthesize audio. Only real call sites may
match ``_SYNTH_CALL``, so blank every COMMENT/STRING token span (spaces,
not deletion, to keep the layout the regexes were written against).
Unparseable source falls back to the raw text — fail closed, a module we
can't tokenize still gets scanned.
f-strings stay conservative (Greptile P1 on #1564): on Python ≤3.11 the
whole f-string — replacement expressions included — is ONE STRING token,
so blanking it would let ``f"{backend.generate(t)}"`` evade the guard.
f-prefixed strings are therefore kept raw there (a literal f-string
*mentioning* a primitive false-positives toward the allowlist — fail
closed). On 3.12+ (PEP 701) replacement code arrives as ordinary tokens
and only the literal FSTRING_MIDDLE text is blanked.
"""
fstring_middle = getattr(tokenize, "FSTRING_MIDDLE", None)
lines = src.splitlines(keepends=True)
try:
tokens = list(tokenize.generate_tokens(io.StringIO(src).readline))
except (tokenize.TokenError, IndentationError, SyntaxError):
return src
for tok in tokens:
if tok.type == tokenize.STRING:
prefix = tok.string.split(tok.string[-1], 1)[0].rstrip("\"'")
if "f" in prefix.lower():
continue # pre-3.12 f-string: may contain executable code
elif tok.type not in (tokenize.COMMENT, fstring_middle):
continue
(srow, scol), (erow, ecol) = tok.start, tok.end
for row in range(srow - 1, erow):
line = lines[row]
lo = scol if row == srow - 1 else 0
hi = ecol if row == erow - 1 else len(line.rstrip("\r\n"))
lines[row] = line[:lo] + " " * (hi - lo) + line[hi:]
return "".join(lines)
def _py_files():
for sub in ("api", "services", "worker"):
for p in sorted((_BACKEND / sub).rglob("*.py")):
@@ -84,9 +126,11 @@ def _py_files():
def test_every_synthesis_module_routes_through_mark_synthetic():
offenders = []
for rel, src in _py_files():
if not _SYNTH_CALL.search(src):
if not _SYNTH_CALL.search(_code_only(src)):
continue
if rel in _ALLOWED or "mark_synthetic" in src:
# The satisfying reference must be code too — a comment saying
# "mark_synthetic" must not certify a module (CodeRabbit, #1564).
if rel in _ALLOWED or "mark_synthetic" in _code_only(src):
continue
offenders.append(rel)
assert not offenders, (
@@ -100,7 +144,7 @@ def test_every_synthesis_module_routes_through_mark_synthetic():
@pytest.mark.parametrize("rel", _PRODUCERS)
def test_known_producer_still_marks(rel):
src = (_BACKEND / rel).read_text(encoding="utf-8")
assert "mark_synthetic" in src, (
assert "mark_synthetic" in _code_only(src), (
f"{rel} lost its mark_synthetic call — its synthetic audio would ship "
"without the Art. 50(2) provenance mark (#1169)."
)
@@ -127,12 +171,34 @@ def test_allowlist_is_not_stale():
p = _BACKEND / rel
assert p.is_file(), f"watermark-coverage list names a missing file: {rel}"
for rel in _ALLOWED:
assert _SYNTH_CALL.search((_BACKEND / rel).read_text(encoding="utf-8")), (
assert _SYNTH_CALL.search(_code_only((_BACKEND / rel).read_text(encoding="utf-8"))), (
f"{rel} no longer matches a synthesis primitive — remove it from "
"tests/test_watermark_route_coverage.py so the guard stays sharp."
)
def test_prose_mentions_are_not_producers():
"""The ee35d238 regression: a comment (or log string / docstring) naming a
synthesis primitive must not make a module a producer — only a call can."""
prose = (
"# A generic backend.generate() call accepts the same wire shape\n"
'MSG = "route through generate_with_cached_ref(model) instead"\n'
"def f():\n"
' """Docs may mention _run_inference( freely."""\n'
" return 1\n"
)
assert not _SYNTH_CALL.search(_code_only(prose))
real = "def f(backend):\n return backend.generate(text='hi')\n"
assert _SYNTH_CALL.search(_code_only(real))
# Greptile P1: a call inside an f-string replacement field is code and
# must still be caught, on every supported Python (≤3.11 tokenizes the
# whole f-string as one STRING; 3.12+ splits out the expression tokens).
fstring_call = 'def f(backend):\n return f"{backend.generate(text=\'hi\')}"\n'
assert _SYNTH_CALL.search(_code_only(fstring_call))
# ...and a comment claiming mark_synthetic must not certify a producer.
assert "mark_synthetic" not in _code_only("# routes via mark_synthetic\nx = 1\n")
# ── mark_synthetic unit contract (delegation, not new policy) ────────────────