Skip to content

rules.md's normative example names feed no differential corpus — 113 uncovered, and 12 moved this cycle unnoticed #414

Description

@derek73

The three differential corpora draw from v1's test banks (corpus.jsonl), the issue tracker (corpus_issues.jsonl) and the CJK rows of the case table (corpus_cjk.jsonl). None of them reads docs/design/rules.md.

That leaves the project's most reviewed names outside the differential gate:

rules.md example names (distinct):   156
of those, in no corpus:              113
of those, MOVED 2.1.0 -> 2.2 branch:  12

Why the doc tests are not already this

The instinct is that rules.md examples are well pinned, since test_rules_doc.py executes every one. But they are self-updating pins: when behavior changes deliberately, the expected value is edited in the same commit and the test goes green. A doc example cannot warn about the change that edited it.

The corpus is the opposite kind of guard. It compares against a released baseline that cannot be edited, so a moved name arrives UNEXPLAINED and has to be classified in a ledger with a written justification.

PR #409 is a worked example. rules.md#M2 carried:

"Jane de la née Jones"      →  family="de la née Jones"

and #409 changed it to family="de la". The doc test followed the edit. Nothing independent observed the movement — the only reason it is explained anywhere is that the author chose to explain it. The name is in no corpus, so the gate never saw it.

The 12 that moved

All intended changes from this cycle, which is the healthy result — adopting this is classification work, not bug-hunting:

Beethoven, Ludwig van          middle 'van' -> ''        last -> 'van Beethoven'      #379
Berg, Jan van der              middle 'van der' -> ''    last -> 'van der Berg'       #379
Berg, Jan vd                   suffix 'vd' -> ''         last -> 'vd Berg'            #380
Jong, Anke de                  middle 'de' -> ''         last -> 'de Jong'            #379
Nguyen, Thi Van                middle 'Van' -> ''        last -> 'Van Nguyen'         #379
Mc Donald                      first 'Mc' -> ''          last -> 'Mc Donald'          #385
Sir de Mesnil                  first 'de Mesnil' -> ''   last -> 'de Mesnil'          #367
abd Allah Smith                first 'abd' -> 'abd Allah'                             #400
Salam, abd Allah               first 'abd' -> 'abd Allah'                             #400
Jane de la née Jones           last -> 'de la'           maiden '' -> 'Jones'         #399
Jane van der Berg née Jones    last -> 'van der Berg'    maiden '' -> 'Jones'         #399
John van der Berg née Jones    last -> 'van der Berg'    maiden '' -> 'Jones'         #399

Relationship to #413

Nearly disjoint, so both are worth doing and neither subsumes the other:

#413 would add (backtick-only names from issues):   104
rules.md names in no corpus:                        113
overlap:                                              9
of the 12 moved names, reachable via #413:            4

The other eight are reachable only from the doc — they appear in no issue at all.

Shape of the fix

A fourth builder with the same shape as build_cjk_corpus.py, which is the closest precedent and already solves the hard parts:

  • Derive from the reviewed source rather than a hand-maintained list, so a name enters the corpus by being written down where it already gets reviewed.
  • Harvest with the doc's own parser (tests/v2/rules_doc.parse_rules_doc), not a second regex — the same argument that made the CJK builder use the shipped script table.
  • Pin the checked-in file against the builder in test_ledger_guards.py, so a stale corpus fails the suite rather than silently narrowing the gate.
  • Ignore the examples' policy annotations. The corpus carries name STRINGS and the run parses them with the default facade; a family-first-scoped example is simply one more name to diff, exactly as build_cjk_corpus.py argues for its zh-scoped rows.

Two things to decide rather than assume:

  • Boundary strings. rules.md deliberately includes '(', '.,', "Anna () Smith" and similar. Over-collection is the established position across the other builders ("costs one parse and produces no diff"), so these are probably fine, but they are more concentrated here than elsewhere.
  • Ledger work. The 12 above arrive UNEXPLAINED on the first run and need rules in up to three ledgers. Several are already explained by existing rules for the same fix, so some will classify without new entries — worth measuring before writing any.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions