Repository navigation
HumanName('Scott E. Werner').initials() drops the middle initial — the facade reads E as the conjunction #462
Description
HumanName("Scott E. Werner").initials() # 'S. W.' -- the middle initial is gone
HumanName("john E. smith").initials() # 'j. s.'
HumanName("Juan Y. Garcia").initials() # 'J. G.'E and Y are the Latin one-letter members of CONJUNCTIONS, and initials() filters conjunctions out. A middle or family initial that happens to be one of those letters is silently dropped.
A v1 parity break, shipped since 2.0.0
Measured on the released wheels:
| input | 1.4.0 | 2.0.0 | 2.1.0 |
|---|---|---|---|
Scott E. Werner |
S. E. W. |
S. W. |
S. W. |
john E. smith |
j. E. s. |
j. s. |
j. s. |
Juan Y. Garcia |
J. Y. G. |
J. G. |
J. G. |
mechanisms.md#FACADE-CONTRACT promises that 1.4-warning-free code keeps working through 2.x "EXCEPT release-log-classified fixes". No release-log bullet classifies this.
The 2.0 core gets it right — only the facade regressed
Same library, same name, two answers:
parse("Scott E. Werner").initials() # 'S. E. W.' correct
HumanName("Scott E. Werner").initials() # 'S. W.' wrongThe boundary is intact, which is what makes this precise
Only the dotted form is affected. A bare one-letter conjunction is still correctly dropped on both versions:
'maria y lopez' -> 'm. l.' 1.4.0 and 2.x agree
'john e smith' -> 'j. s.' 1.4.0 and 2.x agree
So this is not "conjunctions should initial". It is that v1 distinguished the conjunction e from the initial E. by the period, and the facade lost that distinction.
Reach, measured over the differential corpus
Comparing 1.4.0 against 2.2.0dev over the 1094-name corpus, restricted to the 865 names that parse byte-identically on both (so a parse change cannot be mistaken for this one), and comparing flattened letter sequences so 2.x's initials_list regrouping does not count:
14 of those 865 lose an initial, and every one is a middle E:
Amy E Maid · Amy E. Maid · Doctor, Jane E. · E Anne D,Leonardo
JOSE E MARIA SANTOS · Joe E. Smith · John E Smith · Jose E Maria Santos
Jose E. Maria Santos · Rt. Hon. Paul E. Mary · Smith, John E, III, Jr
US Magistrate-Judge Elizabeth E Campbell · john e. smith · scott e. werner
A fifteenth name, de los Santos (lS → S), is not this defect — los is in particles, not conjunctions, and that change is #402/#404's, already classified.
The Cyrillic half is sharper than the Latin one
The shipped single-letter conjunctions are &, e, y, и, й, і, و:
HumanName("Ivan И. Petrov").initials() # 'I. P.' facade
parse("Ivan И. Petrov").initials() # 'I. И. P.' core_vocab.is_initial narrows by script repertoire (#320) precisely so an initial-shaped Cyrillic letter reads as an initial. The facade's predicate consults neither the shape half nor the repertoire half.
Cause
nameparser/_facade.py:474:
def _is_conjunction(self, text: str) -> bool:
self._resolve()
return _normalize(text) in self._lexicon.conjunctionsv1's is_conjunction excluded initials. _process_initial's comment four lines below states it copies "v1 parser.py:427 verbatim", and the copy dropped the carve-out.
The rule is stated and pinned elsewhere in the tree — nameparser/_render.py's _cap_word comment says "v1's is_conjunction excludes initials: 'E.' in 'Scott E. Werner' is an initial, not the conjunction 'e' (pinned live 2026-07-17)", using this very name. The core honors it; the facade does not.
Suggested fix
Give _facade._is_conjunction the initial carve-out the core already applies, so the facade and parse() agree. nameparser/_render.py's _INITIAL is the same shape test, and tests/v2/test_regex_sync.py already pins it against nameparser/_pipeline/_vocab.py.
Worth checking with it: _is_conjunction is one of the v1 hook names listed in _facade.py's hook roster, so a subclass may override it — whether the carve-out belongs in _is_conjunction or at its call site in _process_initial is a real question, and the hook contract should decide it rather than convenience.
Also worth a look while there: whether any other _facade predicate dropped a v1 carve-out the same way. _is_conjunction was found by checking one path; the roster has seven more.
Found reviewing #458, which fixed the equivalent re-derivation in the core's _cap_word.
Activity
docs: the false claims a five-agent review of #463 found, re-measured
docs: the seven findings a design-docs review of #463 raised
fix(facade): keep an initial-shaped conjunction letter in initials() (#…
tooling(differential): compare initials() on roles-identical names (#484
docs(design): the initials view in the differential, and the facade's…
review round: the initials view's own numbers, and the entries it ret…
Merge pull request #494 from derek73/claude/v2-3-prioritization-ca7dea
fix(derek73#383/derek73#479): a single-letter connective joins only o…
fix(derek73#528): HumanName.initials() reads the parse's connective tags
docs(design): review corrections to the rule-order arc, and two stale…
tooling(differential): the three the first sweep identified and skipped