diff --git a/docs/design/decisions/suffix-acronym-collisions.md b/docs/design/decisions/suffix-acronym-collisions.md index 196e8323f..3acd107fa 100644 --- a/docs/design/decisions/suffix-acronym-collisions.md +++ b/docs/design/decisions/suffix-acronym-collisions.md @@ -21,3 +21,4 @@ Closes #342 (a wordlist question) and #454 (a rules.md question) together, becau - **Measurement (2026-09-25, #540).** No corpus name written before this change carries a bare trailing `meng` or `lac` (the `tools/differential/corpus*.jsonl` glob at 120033b5), so the population that could move is this change's own shape-tagged case rows, and every mover is one of them. Classified by `fix(#540)` rules: at each 2.x baseline `wang meng` and `tran lac` move {family, suffix, _ambiguities}, `john smith MEng` and `John Smith MEng PhD` move {middle, family, suffix, _ambiguities}, and `john smith meng` and `nguyen van lac` `_ambiguities` alone; `Smith, John MEng` moves {middle, suffix, _ambiguities} at 2.x and {middle, suffix} at 1.4.0; `Smith, meng` and `Smith, MEng` move {given, suffix, _ambiguities} at 2.x and nothing at 1.4.0 (1.4.0's own reading); `John Smith, PhD MEng` moves {given, middle, family, suffix, _ambiguities} and `john smith, phd meng` {given, family, suffix, _ambiguities} at 2.x (without `_ambiguities` at 1.4.0); `Nguyen Van Lac` moves {family, suffix, _ambiguities} at 2.x and {family, suffix} at 1.4.0; and `Wang M.Eng.` moves {family, suffix, _ambiguities} at 2.x only, 1.4.0 reading the same family for an unrelated reason (its two-piece rule -- a lone word after the given name is the family -- not S2's gate). `nguyen van lac` also diffs at 1.4.0 on `_initials` (`n.` → `n. v.`) for fix(#385/#402)'s reason — its family `van` is a one-particle part — and joins that rule's literal list; the same case-insensitive regex also reaches `Nguyen Van Lac` at every baseline, without explaining anything there (its own family move, at 1.4.0 too, is explained by the Title-case Lac rule instead). Read today's intentional counts off the `corpus:` line of `uv run python tools/differential/compare.py --baseline X`; this change raised them by seven at 1.4.0 and by thirteen at each 2.x baseline. - **2026-09-27 (#544) — #540's two pending questions are answered, and the #540 bullet stands as it landed.** The chunked dotted spelling passes S2's period gate — `Wang M.Eng.` reads suffix 'M.Eng.' as `Wang M.A.` does, and as 2.0.0 through 2.3.0 read it — and the comma is kept: a credential run after a full name that ends in a member is the credential run by C1's name-word count (rules/C4 since #728) (`John Smith, PhD MEng` suffix 'PhD MEng'; `Jane Doe, MS LAc` suffix 'MS LAc' where #540 left title 'MS', given 'LAc', at the cost, accepted in decisions/S7, of `John Smith, Ms Ma` reading suffix 'Ms Ma'). The walk-stopping cost that bullet lists for a run ENDING in a member goes with them, by S2's company clause: `Mary Jones PhD MEng` and `Jane Doe MS LAc` read the whole run as a suffix again. Where the member LEADS the run nothing speaks for it, so `John Smith MEng PhD` keeps its cost. The `fix(#540)` ledger rules for the comma run and the dotted spelling are retired. `fix(#544)` rules classify the comma-run names; `Wang M.Eng.`, whose roles every release from 2.0.0 read, is classified by `feat(#449)`'s given-or-family report rule at 2.0.0 through 2.2.0 and by the dotted `fix(suffix-routing)` rule beside `Jack M.A.` at 1.4.0, and differs from 2.3.0 not at all. The case rows the #540 bullet cites were renamed with the readings they pin: `a_declined_ambiguous_pick_stops_the_walk` is `a_credential_in_front_anchors_a_declined_pick` (`abdul Smith Jr Ma`, suffix 'Jr Ma'), and `comma_credential_run_ending_in_meng_re_reads_the_comma` and `comma_lower_credential_run_ending_in_meng_re_reads_the_comma` are `comma_credential_run_ending_in_meng_keeps_the_suffix_comma` and `comma_lower_credential_run_ending_in_meng_keeps_the_suffix_comma`. The decision and its measurements are decisions/S7's #544 entry. +- **2026-10-18 — cva[22], gaee[14] and np[18] left SUFFIX_ACRONYMS: Wikipedia footnote marks, not credentials.** All three arrived with the `af5bdab` bulk import (2019-12-11), the bracketed number being the source page's reference mark copied along with the acronym; the 3.0 vocabulary spec's migration spike found them. They matched only a token written with the mark itself, so `John Smith NP[18]` read suffix `NP[18]` and now reads family `NP[18]`, and nothing else moves: `np` and `cva` have clean entries of their own, and `gaee` never had one (`John Smith GAEE` reads family `GAEE` before and after). Whether GAEE should be added as a clean entry is a separate vetting question, not taken here. A bulk import from a wiki page carries its reference marks: check a new list for brackets before it lands. Recompute that no vocabulary entry holds one: `uv run python -c "from nameparser import Lexicon; L = Lexicon.default(); print(sorted(w for f in ('titles', 'suffix_acronyms', 'suffix_words', 'particles', 'conjunctions', 'bound_given_names', 'maiden_markers') for w in getattr(L, f) if set(w) & set('[]')))"`. diff --git a/nameparser/config/suffixes.py b/nameparser/config/suffixes.py index 8cbe09345..0f77676c5 100644 --- a/nameparser/config/suffixes.py +++ b/nameparser/config/suffixes.py @@ -679,7 +679,6 @@ 'cua', 'cusp', 'cva', - 'cva[22]', 'cvo', 'cvp', 'cvrs', @@ -784,7 +783,6 @@ 'fsa', 'fsdp', 'fws', - 'gaee[14]', 'gba', 'gbe', 'gc', @@ -925,7 +923,6 @@ 'ndtr', 'nmd', 'np', - 'np[18]', 'nraemt', 'nremr', 'nremt',