Skip to content

Count a listed surname spelling inside a compound surname (Smyth-Jones / Smith) - #1285

Merged
derek73 merged 8 commits into
masterfrom
fix/issue-1262-listed-spellings-in-compound-surnames
Nov 10, 2026
Merged

derek73 merged 8 commits into
masterfrom
fix/issue-1262-listed-spellings-in-compound-surnames

Conversation

@derek73

@derek73 derek73 commented Nov 10, 2026

Copy link
Copy Markdown
Owner

Closes #1262

A surname spelling listed in a lexicon now counts inside a compound surname, as it does for the whole word. With smyth added as a spelling of smith:

>>> lex = Lexicon.default().add("smyth", kind="family", same_as="smith")
>>> m = Parser(lexicon=lex).matching()
>>> m.check("Ann Smyth-Jones", "Ann Smith")["family"].outcome.value
'part-of-other'      # was 'conflict'
>>> m.check("Ann de Smyth", "Ann Smith")["family"].outcome.value
'particles-aside'    # was 'conflict'

Both outcomes are in the default accept set.

What changed in _match.py

The two family leniencies used to compare words by fold alone. Each now also accepts a listed spelling, read in the family group:

  • particles-aside holds where the bases are equal once folded, or have as many words and each pair is equal or listed as one spelling.
  • part-of-other holds where every word of one base (a hyphenated word by its halves) is among the other's, equal or listed. Covering just one word is not enough: Ann Smyth-Jones / Ann Smith-Brown still conflicts.

Each word's spelling set is built once per family comparison (_SpellingSets). That keeps the check near master's cost.

Two things are unchanged:

  • Keys: they already cut every family word's and every hyphen half's spellings, so a pair this makes consistent shares a key.
  • Group scoping: a given name's spelling still never counts inside a surname (Jack Wm-Lee / Jack William conflicts).

What moves under the shipped vocabulary

All 37 shipped surname spellings are particle spellings (el-→al-, mc→mac, ua→ó, binte→binti). A joined particle is set aside before either leniency compares, but an unjoined one stays in its base. So a family made only of particles now reads its listed spellings: Ann Mac / Ann de Mc goes from conflict to part-of-other.

Measurement Result
Grid of particle-only families (28,680 pairs) 207 move, all conflict → part-of-other, the reading the whole word already took (Mac, Ann / Mc, Ann is listed-spelling on master)
tools/differential/match_diff.py --base <master> 0 of 622,140 rows moved; its draw holds no particle-only family
Key guarantee 0 consistent pairs without a shared key, on either tree

Otherwise the change reaches only a caller's own surname spellings. Two tests hold it:

  • test_a_listed_surname_spelling_counts_inside_a_compound_surname: its six leniency rows fail on master, and its conflict rows (two compound surnames sharing one word, two family-comma bases differing in one word, a surname listed as a particle) pass on both trees.
  • test_listed_compound_surnames_keep_the_key_guarantee_and_symmetry: a grid of compound surnames under such a lexicon, checked under every setting.

Also

Review

Four aspects ran on the first commit:

  • code-reviewer: fuzzed 67k caller-lexicon pairs for symmetry and the key guarantee;
  • pr-test-analyzer: 13 mutants, which found the subset rule, the multi-word base and the given-group test unguarded;
  • comment-analyzer;
  • design-docs-reviewer: found the particle-only family moves.

silent-failure-hunter and type-design-analyzer were skipped, since no validation, fallback or public type changed. The fix commits were re-reviewed. One problem predating this change came up: under across-roles, a particle-only family can match a maiden name and share no key. It reproduces on master and is drafted as a separate issue.

🤖 Generated with Claude Code

derek73 and others added 8 commits November 9, 2026 17:14
particles-aside now holds where the two bases are listed spellings word
for word, and part-of-other where each word of one base is among the
other's or listed as a spelling of one of them, in the role's same_as
group: with smyth listed as smith, Smyth-Jones / Smith reads
part-of-other and de Smyth / Smith particles-aside, where both read
conflict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1262

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…w reads

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iew found unguarded

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ts base

The shipped particle spellings do reach the change through a family of
particles alone (Ann Mac / Ann de Mc, 207 of a 28,680-pair grid move
from conflict to part-of-other); match_diff's draw holds no such family.
The Standing line, usage.rst and the entry say so, and count the rows
that fail on master correctly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…'s text

The step's condition was reworded twice in #1262, and each time the
literal the test removed stopped matching.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e grid's settings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 self-assigned this Nov 10, 2026
@derek73 derek73 added this to the 3.1 milestone Nov 10, 2026
@derek73
derek73 merged commit 0e4bd46 into master Nov 10, 2026
14 checks passed
@derek73
derek73 deleted the fix/issue-1262-listed-spellings-in-compound-surnames branch November 10, 2026 01:58
@derek73 derek73 added the matching Name matching: Parser.matching(), check() and keys() label Nov 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement matching Name matching: Parser.matching(), check() and keys()

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should a listed surname spelling count inside a hyphenated or particle-led surname? (Smyth-Jones / Smith conflicts even with Smyth listed as Smith)

1 participant