Skip to content

Count a credential word opening a comma name as a name word (rules/C3) - #1017

Merged
derek73 merged 5 commits into
masterfrom
fix/c3-leading-credential-name-word
Nov 3, 2026
Merged

derek73 merged 5 commits into
masterfrom
fix/c3-leading-credential-name-word

Conversation

@derek73

@derek73 derek73 commented Nov 3, 2026

Copy link
Copy Markdown
Owner

What

rules/C3 (counting the words before the comma) passed over a listed suffix word wherever it stood. So a two-word name whose first word is also a credential read as the listing form's one-word surname, and lost its given name:

Input master / 2.8.0 This PR
JP Clancy, MD family JP Clancy given JP, family Clancy
A.M. Barrett, MD family A.M. Barrett given A.M., family Barrett
Cem Akin, M.D., Ph.D. family Cem Akin given Cem, family Akin
Md Rahman, PhD family Md Rahman given Md, family Rahman
Dr. Md Rahman, Ing given Ing, family Md Rahman given Md, suffix Ing
Cem Gabay, Prof. title Prof., family Cem Gabay given Cem, family Gabay

With no comma, position decides what a word opening a name is (rules/S2): Md Rahman gives given Md, and PhD Smith gives given PhD. The comma count was the one place that asked the vocabulary there. The fix: a suffix word opening the part is a name word to the count where a name word follows it, so the part reads as it does alone, under every order. Both counts change:

  • _comma._whole_name, the unambiguous credential's count;
  • _vocab.name_word_count, the ambiguous class's count of names (C4), where the opening word is the first one behind any titles.

Edges:

  • A title/suffix dual opening the part counts as the title it also is: Sr. van der Berg, PhD reads as Dr. van der Berg, PhD does.
  • A title behind the opening word is no name word: Md Prof., PhD keeps family Md Prof..
  • A split credential's member stays half a credential (rules/S12): MB ChB, PhD keeps Phase 2: derive ambiguity from clashing readings and extend the gate to every reading kind #752's reading.
  • A suffix word ending the part still counts as none: Smith Jr., PhD → family Smith.
  • A suffix word with nothing behind it changes nothing: Md, PhD → family Md.

Found by running the spec of hoenth/name_splitter, a Ruby gem, through parse(). Its Same Barker, Ph.D. read family Same Barker, because same is a listed credential.

Measured (2026-11-02, against origin/master c1ceb3b)

Local corpora. Every entry holding a comma across the 13 local corpora: 2,216,662 entries, default policy, seven fields plus ambiguity kinds compared.

  • 3,167 entries could move: two or more words before the comma, opening with a listed suffix word.
  • 89 move: ctgov-officials 80, orcid-researchers 6, fec-individuals 3.
  • 82 of those gain the given name the head opens with. The other 7 are listed in decisions/C3: 4 heads whose given name had been a credential, 2 Md. heads that H2 now reads as a title, and one entry holding two names. FEC's 3 moves are organizations.
  • No move changes only a report.

Against the releases, over all 89 new readings:

  • 52 match 1.4.0, 60 match 2.3.0, and 0 match 2.8.0.
  • A credential after the comma is mostly a 2.4.0 regression undone: JP Clancy, MD and Cem Akin, MD gave given JP and Cem in 1.4.0 through 2.3.0.
  • A title after the comma reads as no release read it (Cem Gabay, Prof.). That accounts for 17 of the 29 entries 2.3.0 read differently.
  • Md Rahman, PhD never had a given name in any release.

Committed corpora. No existing entry moves. snapshot.jsonl and corpus_rules.jsonl only gain the 12 new rule examples, and the CLDR and GND agreement records are unchanged.

Invariant. The new test_a_head_before_a_credential_reads_as_it_does_alone covers 19 opening words × 6 bodies × 6 credential parts × 3 orders = 2,052 rows. Each row, suffix aside, must read as its head alone. All 2,052 hold; 1,062 fail on master (the recorded negative control).

Frame cost (sys.setprofile call events): unchanged on Smith, John, John Smith, PhD, John Smith, MA, JOHN SMITH, MD and Jane Doe, MD, FACS. Only the heads that now move cost more, since they take the whole-name path.

Declined: giving md a name reading

Giving md an abbreviated-given-name reading (same_as="muhammad") would fix the Md heads by vocabulary, but it makes md part of the ambiguous credential class:

The count fix reaches the Md heads without any of that, and also reaches the initials and Cem.

Not decided here: a Md inside a name starts a suffix (Badrul Akmal Hisham Md Yusoff → suffix Md Yusoff). That's a separate gap.

Review

A code review and a design-docs review ran on the first commit.

  • Code review: no high-confidence defect. Its finding that the two counts disagreed on a title behind the opener is fixed.
  • Design-docs review: nine findings, all applied:
    • the release history, now measured over every moved entry instead of one shape;
    • the Declined figures, recomputed;
    • the rule's wording, which held under the default order only;
    • the dual case, now stated in the rule;
    • a fence row that didn't witness the change;
    • the grid figures, replaced by the invariant test;
    • the C3 clause, which now cites S2 for position instead of restating it;
    • the AGENTS.md misstatement of Md's history;
    • the #PRNUM placeholders, filled in after this PR was opened.
  • Left as is: decide's counts include a maiden clause's words, which C12's front leaves out. That's pre-existing, and no input changes because of it.

Docs

  • rules/C3: the new bullet with its examples, and a Because sentence citing S2. The budget is re-recorded. The clause defines what C3's count counts, as "A title in front is a word to the count" already does, and cites S2 for position instead of adding a signal.
  • decisions/C3: a Standing line and a dated entry with the measurements, the recipe and the declined alternative.
  • rules/README.md: the glossary entry for "name word".
  • nameparser/AGENTS.md: the one-word-path sweep now asks for a credential-spelling word at the head of every comma grid, and a title behind it.
  • Release log: a Behavior Changes bullet.

Tests

  • 8 case rows and the invariant test; the field and alternative sweep counts are re-recorded.
  • The P7 negative control is re-taken (classify 404 → 403).
  • On the merged tree: full suite (35,017), the serial benchmarks, ruff and mypy all pass. The suite also passed on 3.15 before the review fixes.

🤖 Generated with Claude Code

derek73 and others added 3 commits November 2, 2026 20:41
…(rules/C3)

Both counts of the part before a comma passed over a listed suffix
word wherever it stood, so a two-word name that a credential word
opens read as the listing form's one-word surname: 'JP Clancy, MD'
read family 'JP Clancy' (2.4.0 through 2.8.0), as did initials that
spell a credential ('A.M.'), given names a credential spells ('Cem')
and the given name 'Md'. The word opening the part is in the given
name's place, so it counts as the given name it reads as with no
comma; behind titles in the ambiguous class's count, and never a
split credential's member (rules/S12).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The code review found the two counts disagreeing where a title follows
the opening word ('Md Prof., PhD' moved in `_whole_name` but not in
`name_word_count`); a title behind it is no name word now in both. The
design-docs review found the decisions entry's release history spot-
checked on one shape (now measured over all 89 moves against the
wheels), the Declined figures unreproducible (recomputed), the rule's
wording true under the default order only, a fence row that did not
witness the change, the grid figures without a recipe (replaced by
test_a_head_before_a_credential_reads_as_it_does_alone, with its
negative control), and nameparser/AGENTS.md misstating Md's history.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 self-assigned this Nov 3, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 added this to the 3.0 milestone Nov 3, 2026
codecov/patch found the two `members.add` lines unreached: no test put a
split credential's member at the head of a part whose count is the
ambiguous class's or the one-letter numeral's. 'MB ChB, Ing' fails with
the member counted (suffix 'Ing'); the numeral's path ends at a later
check either way, so `_members` and `name_word_count`'s parameter are
tested directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73
derek73 merged commit 69a0e6f into master Nov 3, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant