Skip to content

The one fields-only ledger rule absorbs any diff of its shape, and no guard can see it grow #451

Description

@derek73

tools/differential/expected_since_1.4.0.toml's fix(suffix-routing) two-token name with unambiguous trailing suffix stays suffix is the only rule in any of the three ledgers with no name_regex:

# tomllib over all three ledgers
expected_since_1.4.0.toml: 59 rules, 1 with NO name_regex
expected_since_2.0.0.toml: 58 rules, 0
expected_since_2.1.0.toml: 51 rules, 0
issue = "fix(suffix-routing) two-token name with unambiguous trailing suffix stays suffix"
# 'Johnson PhD' / 'Smith Jr.' / 'John V' / 'QC MP': ... Four corpus names,
# and the prose fits all four.
fields = ["given", "family", "suffix"]

It explains 14 names today, not four.

Why this shape absorbs silently

compare.py admits a rule when diff_fields <= set(fields). With no name_regex, this rule claims any name whose diff fits {given, family, suffix} — a very common shape — so a newly-moved name lands under it and the gate stays green with nothing to read.

The guard cannot see it either. _CORPUS_CLAIMS records names as "corpus names the name_regex reaches; the whole corpus when a rule has none" — so this rule's entry is _Claim(1090, ('family', 'given', 'suffix'), …), the entire corpus. It is already at its maximum, so arrivals never move it. test_every_rule_claims_the_recorded_share_of_the_corpus passes whether the rule explains 4 names or 40.

It has absorbed real movements twice

So the ledger's central promise — that every behaviour change is classified in writing, by the rule that caused it — is not held for any diff of this shape at the 1.4.0 baseline.

Worth deciding

Whether a fields-only rule should be permitted at all. compare.py's validate_rules currently allows it (the docstring calls it "the most unbounded shape validate_rules permits"), and _CORPUS_CLAIMS's comment already names it as the shape "most worth writing down" — the recording exists precisely because the risk was understood.

Options, roughly:

  1. Give it a name_regex. It explains 14 names; an anchored alternation would bound it and make _CORPUS_CLAIMS meaningful. Cheapest, and it matches what fix(post_rules): H1 counts name words, not annotations (#410) #444 and Ledger rules classify diffs they do not describe, and a rule that stops explaining anything is invisible #372 already did piecemeal.
  2. Forbid fields-only rules in validate_rules. Structural, and there is exactly one to migrate. Would need a rule for any legitimately open-ended class.
  3. Make the guard see reach rather than regex coverage. Record what a rule explains, not what its regex matches, so a growing catch-all fails the guard. Larger change; would make every rule's claim tighter.

Its comment says "Four corpus names, and the prose fits all four" — that has been wrong since at least #414's rules-corpus harvest, and nothing recomputes it. Whatever is decided, that figure should either become a recompute one-liner or go.

Raised from #450's review, where the same shape was found still absorbing after a targeted narrowing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions