@@ -253,21 +253,26 @@ def _is_latin_only(name: str) -> bool:
253253 return all (ord (ch ) < 0x250 for ch in name )
254254
255255
256- def validate_rules (rules : list [dict [str , object ]]) -> None :
256+ def validate_rules (rules : list [dict [str , object ]], ledger : str ) -> None :
257257 """Reject malformed allowlist rules LOUDLY at startup. A rule with
258258 neither name_regex nor fields would match every diff and shadow
259259 every later rule -- the harness would report false confidence,
260- the exact failure it exists to prevent."""
260+ the exact failure it exists to prevent.
261+
262+ `ledger` is named rather than hardcoded because there is one per
263+ baseline now: a message naming the wrong file sends the reader to
264+ edit a rule that is not the broken one.
265+ """
261266 for i , rule in enumerate (rules ):
262267 issue = rule .get ("issue" )
263268 if not isinstance (issue , str ) or not issue :
264269 raise SystemExit (
265- f"expected_since_1.4.0.toml rule #{ i + 1 } has no string "
270+ f"{ ledger } rule #{ i + 1 } has no string "
266271 f"'issue': { rule !r} " )
267272 if not isinstance (rule .get ("name_regex" ), str ) \
268273 and not isinstance (rule .get ("fields" ), list ):
269274 raise SystemExit (
270- f"expected_since_1.4.0.toml rule #{ i + 1 } ({ issue !r} ) has "
275+ f"{ ledger } rule #{ i + 1 } ({ issue !r} ) has "
271276 f"neither 'name_regex' nor 'fields' -- it would match "
272277 f"every diff and shadow every later rule" )
273278
@@ -287,9 +292,10 @@ def classify(name: str, diff_fields: set[str],
287292
288293def main () -> int :
289294 ap = argparse .ArgumentParser ()
290- # Both corpora by default: they have different blind spots (see
295+ # Every corpus by default: they have different blind spots (see
291296 # build_issues_corpus.py), and one that has to be asked for by name
292- # is one that stops being run.
297+ # is one that stops being run. Deliberately a glob rather than a
298+ # list, so adding a corpus file is enough to put it in the gate.
293299 ap .add_argument ("--corpus" , action = "append" , metavar = "PATH" ,
294300 help = "corpus file; repeatable. Defaults to every "
295301 "corpus*.jsonl beside this script." )
@@ -303,9 +309,9 @@ def main() -> int:
303309 surfaces = _surfaces_for (baseline )
304310 paths = ([Path (p ) for p in args .corpus ] if args .corpus
305311 else sorted (HERE .glob ("corpus*.jsonl" )))
306- rules = tomllib . loads (
307- _allowlist_for ( baseline ) .read_text ()).get ("change" , [])
308- validate_rules (rules )
312+ ledger = _allowlist_for ( baseline )
313+ rules = tomllib . loads ( ledger .read_text ()).get ("change" , [])
314+ validate_rules (rules , ledger . name )
309315 rules = _sorted_rules (rules )
310316 # A glob that matches nothing must not read as "everything passed".
311317 # Comparing zero names would print 0 unexplained and exit 0 -- the
0 commit comments