Case and shape decide a bare ambiguous credential acronym (#289, #516) - #530
Merged
Merged
Conversation
The fact #527 computed as a local in classify becomes a field beside `order`: the suffix slot, the post-comma slot and the tail-segment reading all consult it, and two stages deciding it apart is what recording it prevents. `_pieces.own_words(state)` is the span both sites ask for -- the name's own word texts and the maiden-clause cut. classify hands over the marker-run map it already built and keeps its answer byte for byte; a caller that runs before those tags exist omits it and `_vocab.first_marker_head` walks the texts instead. The two spellings can disagree about the CUT where a phrase-entry head completes no run ('z' of 'z domu'); measured over the 1174 corpus entries, that is two names, and the one-case verdict differs on none. rules.md#P3's `implemented:` list gains `_pieces.py`, which is where its own-words doctrine now lives, and its own-words paragraph says the span is shared with S2 and C1 rather than being P3's alone. No example line moves. No behavior change: every corpus name parses identically, the differential is clean at the default baseline, and the frame count moves by the helper's own call. Refs #289, #516 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
In a name written in more than one case, an ALL-CAPS member of `suffix_acronyms_ambiguous` is written the way a credential is written: `Jack MA` gives given 'Jack', suffix 'MA' where it gave family 'MA'. A member in any other cased form is written the way a surname is written and stays one even with words to spare: `John Smith Ma` gives family 'Ma' where it gave suffix 'Ma'. A lowercase member carries no contrast, a name written wholly in one case carries none at all, and both take the words-to-spare count exactly as before -- `JOHN SMITH MA`, `ANH DO` and `jack ma` do not move. The same reading reaches the comma forms, at three sites rather than two: the trailing peel, the post-comma given slot, and the wholly- suffix test segment asks of its own tail segments. `Smith, MA` gives family 'Smith', suffix 'MA'; `Steven Hardman, MD, DO, DDS` stops reporting `comma-structure`, its third segment now reading as the credential run it is. At a comma the words-to-spare count is of NAME words, so `Smith Jr., MA` keeps its family where a token count would have handed it to `given`, and it reaches the listed set in any case, which restores 1.4.0's reading of `John Smith, Ed`, `john smith, ma` and `JOHN SMITH, MA`. Every decision at these slots reports the existing SUFFIX_OR_NAME, including -- for the first time in this library -- on a comma path. Accepted and pinned rather than repaired: `abdul Smith Jr Ma` reads `Jr` as a middle name, the surname lean breaking the peel at `Ma` before the genuine suffix behind it is reached. Refs #289 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Policy.unlisted_dotted_suffixes, default True: a token of two or
more period-separated chunks that no vocabulary claims joins the
ambiguous credential class by SHAPE, and the words-to-spare rule then
reads it. `John Smith X.Y.Z.` gives suffix 'X.Y.Z.' where it gave
family; `Jack X.Y.Z.` keeps its family and gains the report the fork
always deserved. Case is irrelevant here -- the periods are the
signal -- so `john smith x.y.z.` reads as its mixed-case twin.
Whole-token vocabulary still wins ('M.A.', 'Ph.D.', 'A.B.C.'), a
single trailing period is still not this shape, and a leading dotted
run is untouched. Switch off: name material everywhere, as 2.3 did
for a token no chunk claimed -- the roman-chunk retirement is not
behind this switch -- and the fork is still reported.
The roman-chunk accident retires NARROWLY with it: the chunk rule no
longer fires where every chunk the vocabulary matches is a single
ASCII character, which is measured to be {'2', 'i', 'v'} -- so
`Jack X.Y.I.` reads family again (1.4.0's reading) while 'Msc.Ed.',
'JD.CPA', 'Lt.Gov.' and 'J.씨' keep their chunk-derived readings. The
wide retirement was measured and rejected: it costs a real credential
for nothing this change wants. A bare digit chunk is never an acronym
by shape either ('Smith, 1.4', 'John Smith 1.4' stay name material,
unchanged) -- the shape verdict requires every chunk to be alphabetic.
The class claim says where it came from: `shape:acronym` rides beside
`vocab:suffix-ambiguous`, in a new namespace, because `vocab:` records
membership and the word is not in the vocabulary. The comma form's
own candidate test (`_vocab.ambiguous_class_candidate`) admits a
by-shape member the same way, so `John Smith, A.B.` flips to the
credential run and `Smith, A.B.` reports the fork it declines.
`is_wholly_suffix` never admits the shape class directly -- doing so
bypassed the words-to-spare count entirely and, combined with C1's
legacy token-count disjunct, misread `Smith Jr., A.B.` as a one-word
given; the comma form's structure decision and report both go
through `ambiguous_class_candidate` alone.
Two follow-ups from the previous commit's review, since they touch
the same helper: `_pieces.leans_credential` is renamed `listed_lean`
(the name now says what it returns), and a parametrized test pins
`_vocab.is_title_shaped` and `_pieces.is_leading_title` in agreement
over the union of their own example tables.
Refs #516
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`Policy.unlisted_caps_suffixes`, default False: with it on, an unlisted all-caps word of two or more letters with no interior period, in a name written in more than one case, joins the ambiguous credential class by shape and the words-to-spare rule reads it -- `John Smith XYZ` gives suffix 'XYZ', `John Smith, XYZ` gives given 'John', family 'Smith', suffix 'XYZ'. Off, nothing changes and nothing is reported. Off by DEFAULT, and the asymmetry with the dotted half is the decision rather than an oversight: an all-caps surname is a real writing convention that shape cannot separate from a credential. `Jean DUPONT`, `Jean Pierre DUPONT` and `Minjun KIM` read as family names at 1.4.0, at 2.3 and at this default, and `Jean Pierre DUPONT` gives family 'Pierre', suffix 'DUPONT' with the switch on. A swallowed family name is the worse failure, and default-off is 1.4.0 parity for that whole class. The predicate is `isalpha() and isupper()` at two characters or more, so a digit anywhere disqualifies the token and a single capital stays an initial; UNLISTED excludes anything whole-token suffix vocabulary claims, `MC` among them. The all-caps half is the first shape this class wears across MORE THAN ONE token: `_vocab.ambiguous_class_candidate` gains a `one_case` parameter, and `_segment.py`'s structure decision generalizes its single-token candidate test to a whole post-comma RUN, so `John Smith, LEED AP` reads suffix 'LEED AP' (rules.md#C1's `deviates: #291` line coming true) while its one-pre-comma-word twin, `Smith, LEED AP`, still declines the structure flip and reports through assign's existing family-comma emitter. The membership test is the one candidate check in this class that needs the case fact at all; the run test is gated behind the switch and tried only after the listed/dotted check declines, so a non-candidate comma name (`Smith, John`) still never forces it -- measured 0 frames on that name and its siblings at the default, and 0 on the reference name. `is_wholly_suffix` deliberately still does not see this class, by shape or by run, matching the dotted half's own decision. `tests/v2/test_facade_cases.py`'s `_UNTRANSLATED`/`_CORE_ONLY_IDS` gain the new field and its case rows, the same treatment `unlisted_dotted_suffixes` got: no v1 spelling exists for a by-shape credential class. Refs #516 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
rules.md#S2 gains the written-case evidence beside its count, says
the case is read SECOND at a family comma, carries the opt-in
all-caps shape, and retires the Accepted sentence this arc repairs
("with words to spare, a bare ambiguous acronym reads as a suffix
even beside an East Asian surname it more likely belongs to");
`Jack Wei Ma` moves with it. rules.md#S3 says the chunk rule no
longer fires where every matched chunk is a single ASCII character,
that an unlisted multi-chunk word is read by position, and what the
by-shape class excludes -- a non-alphabetic chunk, a script that
writes no abbreviations, a lone trailing period. rules.md#C1 carries
the comma-quiet exception, scoped to this class, counts NAME words,
puts that count ahead of the written case, and retires both "Both
modes consult the vocabulary alone" and the claim that this is the
one place a comma path reports at all -- C2's flag reports a shape
the parse could not recognize, which `AmbiguityKind`'s docstring now
says too. rules.md#P2, #P5 and #H5's `Ma`/`MA` example lines move
with the readings, and the two Policy switches reach the doc through
the annotation slot, with their off-by-default readings executable
beside the default ones.
Every diff is classified at all five baselines, with the gate's own
output as the authority: new fix(#289) and fix(#516) role rules and
one `_ambiguities` rule per 2.x ledger, fix(#424)'s `fields`
re-scoped for the third reading of `Freiherr von Berg MA`,
fix(#425)'s re-scoped where the surname lean stops one of its two
names diffing at all, fix(#316) gaining the one-case spelling H5
needs to keep demonstrating its own transparency clause, and the esq
rule declared `dormant` where the by-shape class restores a
baseline's own reading by a different route. Dated amendments where
a comment rested on "the two-word Jack Ma is kept intact" -- still
true for that spelling, false for its all-caps twin -- and where
`radar unclassified` being 0 everywhere was load-bearing.
Refs #289, #516
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
decisions.md gains a `### S2` entry -- the first under that key -- for
the whole arc: the lean and the argument for keeping the judged token
in the span, the caseless inertness, the comma extension and its reach
to the listed set, the two switches and why their defaults differ, the
narrow chunk retirement and the wide one that was measured and
rejected, the three reading sites, where the fact lives and the two
options refused on ordering and on bug surface, and the two accepted
costs. Amendments where a landed entry rested on something this change
makes false: the parking lot of #suffix-acronym-collisions is closed,
its roman-numeral bullet retired narrowly, #P3's out-of-scope line
amended, and #ma-do's "the two-word Jack Ma is kept intact" scoped to
the spelling it names. rules.md#S2 and #S3 gain the `history:
decisions.md#S2` trailer the new heading now resolves, and the two
`decisions.md#P3` code citations that recorded the one-case fact
(_classify.py, _state.py) re-point to `#S2`, their better home.
mechanisms.md names `one_case` as STATE-OFFSET-CHANNELS' third
channel and no new entry is owed; the decisions entry says why.
ONE-PREDICATE-PER-QUESTION's roster gains `caps_shape_candidate`, the
one function three sites now share for the all-caps shape test.
AGENTS.md's trailing-abbreviation paragraph gains the trailing shape
rule it said did not exist, for MULTI-chunk dotted words only.
customize.rst documents both switches and rewrites the `Smith, BA`
cost, which is now the one-word family in a case-silent spelling and
nothing wider; usage.rst's `parse("Jack MA").family` doctest becomes
`.suffix`; the release log carries four bullets.
Refs #289, #516
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #530 +/- ##
==========================================
+ Coverage 98.69% 98.73% +0.04%
==========================================
Files 45 45
Lines 3366 3475 +109
==========================================
+ Hits 3322 3431 +109
Misses 44 44 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
… the wordlist roster
Ten findings from a whole-PR review, every one measured before and
after.
A lost report. Where the prefix chain absorbed an acronym the S2 peel
had DECLINED, nobody reported the fork: assign reports from the peel's
picks and a pick reaches it only as a lone piece, so 'John van der
Berg Ma', 'John de Ma', 'Dr. John van Smith Ma', 'John van Smith Ma
Jr.' and 'John Smith Mc Ma' each lost the flag rules.md#S2 promises
for either reading. The emitter now sits at the chain's own merge
(mechanisms.md#AMBIGUITY-AT-THE-DECISION-SITE); roles are unchanged.
It declines where the PARTICLE run took the word instead ('anh van
do', 'anh van mc'), that being P6's fork rather than S2's, and the
`prefix()` call is tested last so the reference name stays at 412.
Two comma readings. script_segment asked `is_wholly_suffix` of the
post-comma run without the case fact segment had just recorded, so
'Kim김민준씨, MA' left the person's own 씨 unpeeled while 'Kim김민준씨,
PhD' peeled it — one name, two credential spellings, two parses. And
segment's tail-segment test is blind to the by-shape class, so the
narrow roman retirement gave 'John Smith, MD, R.A.I.' a
COMMA_STRUCTURE flag 2.3 did not raise; a by-shape class-run test
quiets it, narrowed to exclude LISTED members so the lean's own
negative control ('STEVEN HARDMAN, MD, DO, DDS') still measures
something.
The wordlist roster. `caps_shape_candidate`'s exclusion named eleven
of `_lexicon._VOCAB_FIELDS`' thirteen, so
`Lexicon.default().add(surnames={"dupont"})` still read 'Jean Pierre
DUPONT' as suffix DUPONT — a caller listing a word as a SURNAME and
getting a credential. The roster is now derived from the field tuple,
with a per-field test.
Also: a LISTED dotted ambiguous acronym no longer gets `shape:acronym`
(it silenced the caller's own case lean); `ambiguous_class_candidate`
loses the dead `one_case` parameter and its unreachable caps tail, and
the agreement test's caps rows point at `caps_shape_candidate`, which
is the live predicate; `Policy.unlisted_dotted_suffixes` and
`unlisted_caps_suffixes` move to the END of Policy and PolicyPatch,
where they no longer re-bind 2.3's positional arguments, and the
bool-validation roster is derived from `dataclasses.fields` (the twin
loop in tests had drifted and named neither); `one_case` is REQUIRED
on the four piece predicates that own it; the two lean predicates
carry a `Lean` Literal and `strict_equality` covers `nameparser.*`;
and "vocab:suffix-ambiguous" is a constant beside SHAPE_ACRONYM_TAG.
Measured: 412/449 unchanged, the default comma harness unchanged at
176/207/233/257/225, and all five gates exit 0 with 0 unexplained.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Tests only. Every expected value is measured, and three of them are
not what the review predicted.
Case rows for the live branches no row named: classify's caps branch
reading the NAME-level case past a maiden clause ('née JONES XYZ'),
the one-case comma gate at one token and at a run, `all()` rather than
`any()` over a caps run ('John Smith, LEED BA'), name_word_count's
title and suffix arms ('Mr Smith, Ma', 'Smith Jr, Ma'), the caps
exclusion end to end for three wordlists, `unlisted_dotted_suffixes`
off at all three slots, the declared-order comma flip, and the
script-agnostic claim in the caps switch's docstring measured in
Cyrillic and in accented Latin.
Three rows record ACCEPTED silent moves rather than new behavior: a
digit chunk ('John Smith 1.4.2', 'Smith, 1.4.2', 'John Smith, 1.4.2')
falls out of both the chunk claim and the shape class, so it moves
suffix -> family, and post-comma to `given`, with no report at any
policy. rules.md#S3's narrow retirement is why, and a version string
read as a credential was the same accident it removes.
Two more are rough edges recorded as measured: `Policy(lenient_comma_
suffixes=False)` reads 'Smith V., Ma' as given Smith / family V. /
suffix Ma, and 'Smith V, Ma' as given Smith / suffix 'V, Ma' --
consistent with master's 'Smith V., PhD' under the same knob, so the
knob's reading of 'V.' rather than the credential class's.
Three findings the review's own claims did not survive:
'Andrew Perkins (X.Y.Z.)' now reads suffix, because period-final
delimited content is RELEASED with role None and so is ordinary
trailing material -- which narrows the note on
caps_switch_does_not_reach_delimited_content rather than contradicting
it. 'Smith, A.B.' reports at the default, so it belongs in
test_assign's exactly-one-report loop and the stale reason is gone.
And of the three `_group` `one_case` plumbing sites called inert, only
TWO are: dropping the argument at the maiden walk's pair moves 0 of
14,028 parses (2,338 names under six policies), while dropping it at
the chain-tail measure moves 18 -- 'John van der Berg Ma', 'John de
Ma' and 'Freiherr von Berg MA' under every one of the six. Both
figures are recorded at the call site.
Also: an invariant that `tag_marker_runs` answers in ascending index
order, which `own_words` depends on and nothing said; the
`_MUST_NOT_MATCH` probes for the #516 dotted rule's three unprobed
gates; and the report detail pinned verbatim for the branch that reads
the word as a name.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
decisions.md#S2 gains six dated bullets: what the round moved with
before/after on every name; the DIGIT-DOTTED tokens that move
silently and are accepted; the comma report's actual reach and the
given-segment trailing slot recorded as an open follow-up; the strict
comma knob's rough edge; the "three inert sites" prediction that
survived only two-thirds of its own measurement; and the frame band
after the round. The blast-radius bullet is re-measured, two sets of
figures under one date being the thing it exists to prevent.
Two universal claims are NARROWED to what ships rather than the
emitters widened to match them. `AmbiguityKind.SUFFIX_OR_NAME`'s
member docstring now names the slots it is emitted at and the one it
is not, and rules.md#S3's "and the same at a comma" says which parts
of a comma form it means: `Doe, John MA` reads middle `MA` silently,
in this release as in every other, and that is a boundary rather than
an oversight.
rules.md amendments for the round's own behavior: C2 states the
tail-segment quiet and both ways it is narrow, P2 states the chain's
report and its particle-run exception, W3 states that the honorific
peel reads S2's case evidence. Every clause has an example line; four
of them were added on a self-review pass that found a statement
disagreeing with its own example ('John Smith, MD, Ma' leans NAME,
which is not "leans nothing"), a by-SHAPE clause reaching further
than the code (the caps half does not quiet a tail segment; only the
dotted one does), and two claims with no witness at all.
Comment drift, each verified by a run: assign's "three sites" is
four; its comma-report block no longer says the by-shape member needs
a switch to be reported, nor that two pieces of `Smith, MA PhD`
report; segment's stage header declares the four reads it had left
out and says it reports the structure FLIP rather than "the comma
decided"; the _pieces importer list and its layering entry say four
stages, not two; `_state`'s two rosters are re-counted; classify's
`_NO_INITIALS` sentence no longer claims nothing varies by it, and
the block header describes all four readings in the block; the
one-frame measurement has one home instead of three; and
UNBALANCED_DELIMITER's member now carries the clause the enum
docstring said it did.
Ledger comments: the `esq` rule's "what is gone is its diff" is
scoped per baseline, its own dormant string having said otherwise at
the 2.x three; and "one set for all five ledgers" gains the carve-out
that has been true since 'John Prof. MA' was held out of the 1.4.0
copy. Plan labels ("commit E", "Task 22 Step 2", "Switch A") are
reworded to name the Policy field or the mechanism; the sweep leaves
only pre-existing `#272 Task N` hits.
User docs: the release log's roman-numeral wording becomes "a single
ASCII character" with the digit's consequence spelled out, customize
matches, and the reports inventory names the restored report, both
that go away, and the slot that stays silent. sphinx doctest 253/0,
html -W exit 0.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…npinned branches
Ten findings from a verification pass over the review round, each
re-measured on this tree and, where a "before" or an "every release"
was claimed, on the 2.3.0 and 1.4.0 wheels.
Three claims were false about a released version and are corrected
from measurement rather than narrowed:
- `Freiherr von Berg X.Y.I.` was listed among the names that went
silent. It GAINED a report: 2.3.0 read family `von Berg`, suffix
`X.Y.I.` with `particle-or-given` alone, and the tree reads family
`von Berg X.Y.I.` with `suffix-or-name` beside it. The role moved
into a slot that does not report and the chain emitter reported
instead.
- The release log claimed TWO reports go away and named
`John Smith, MD, R.A.I.` as one. It reports nothing at 2.3.0 and
only ever carried the flag inside this PR's own development. Over
the corpus exactly ONE is lost (`Steven Hardman, MD, DO, DDS`) and
one is SWAPPED (`Jack X.Y.I.`, `given-or-family` →
`suffix-or-name`); the full lost/gained inventory and its recompute
recipe are in decisions.md#S2.
- "as every release has" for `Doe, John MA`: 1.4.0 read it as a
SUFFIX and 2.0.0 onwards as a middle name, so the silence at the
given part's trailing slot is a 2.0-era reading. Corrected in
release_log.rst and _types.py, and recorded in decisions.md#S2's
open bullet, where it makes the slot a 1.4.0 parity question as
well as a noise one.
Three rules stated a reach wider than the parser's. S2's ambiguity
flag is narrowed to the slots that report, with `Doe, John MA` as the
boundary; S3's comma clause said "before a family comma and after it"
and is now the FIRST piece after a family comma and the part before a
SUFFIX comma, all six readings measured; P2's Accepted clause was
scoped to the unambiguous particles (vd, mc) while behavior carries a
`do` carve-out — `suffix_acronyms_ambiguous ∩ particles` is exactly
{do} — now stated by name with a cased boundary row.
Two branches were unpinned and now fail without their code. The chain
emitter's BY-SHAPE tag: replacing the two-tag test with the listed tag
alone passed all 8624 tests, because classify writes both tags at the
default; under `unlisted_dotted_suffixes=False` it silences three
names, and a row for `John van der Berg X.Y.Z.` under that policy
pins it. C2's second narrowing: the caps shape does not reach a tail
segment, pinned by `John Smith, MD, XYZ` under the caps switch, which
fails if `caps_shape_candidate` is folded into the class run. Both
confirmed by runtime monkeypatch with `_pipeline.STAGES` rebound.
Two counts did not reproduce. The review round added TEN corpus names,
not eight, and this pass adds three more (1231 → 1234 at the gate);
the recompute is compare.py's own `_load_entries` over the glob,
deduped, diffed against the same list at an older commit. And the
`one_case` plumbing sweep's population of 2,338 names / 14,028 parses
does not follow from its stated recipe by any reading — the distinct
union is 1,642 / 9,852 — so both are restated here and at the call
sites in _group.py. The FINDING survived re-measurement unchanged: 0
and 18, the same three names, under all six policies.
Also: _assign.py's header claimed the family-comma emitter was the
kind's first appearance on a comma path, which _post_rules.py has
falsified since before this PR (`Berg, Jan vd` reports at 2.3.0), and
called _group.py's "a fifth emitter" when the library has seven. The
claim is dropped and the ordinal replaced with the three modules.
`Doe, John MA` enters the contract corpus and differs from 1.4.0, so
expected_since_1.4.0.toml gains one literal-anchored rule whose
comment says the reading is 2.0-era and this PR did not move it.
Rosters updated from the guard's own messages.
Five gates exit 0; 8638 tests, mypy, ruff, 412/449, doctests and both
sphinx builds clean.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Several sites claimed this PR brings the comma paths' first-ever READING report. False: P6's family-comma attachment fork (nameparser/_pipeline/_post_rules.py) has reported SUFFIX_OR_NAME since 2.3, measured on this tree and at master 1f78bef -- parse("Berg, Jan vd") gives given 'Jan', family 'vd Berg', ambiguities=['suffix-or-name'] -- and AmbiguityKind.SUFFIX_OR_NAME's own docstring already lists that case. What is new in 2.4 is narrower: the comma's OWN structure/credential decision now reports, where it was silent before. Rescoped nameparser/_types.py, _pipeline/_segment.py, _pipeline/_assign.py, the matching test comments, the four differential ledger comments, docs/release_log.rst's bullet lead, rules.md#C1's statement, and decisions.md's S2 entry to say so. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
No behavior change: every corpus and case-row reading (1448 names, four policy combinations, the bare parse and the facade) is byte-identical to e40ac73, and the reference frame counts hold at 412 / 449. The opt-in caps path sheds one frame (212 -> 211, 244 -> 243), the single-use `run_candidate` closure. - _segment: `suffixy` and `leaning_suffixy` become one closure with a `case` default; `run_candidate` is inlined into the caps-run guard. - _state: `_AMBIGUOUS_CREDENTIAL_TAGS` moves beside the two tags it is built from, and _assign asks it instead of spelling the same question as an `or` of two `in` tests. - _vocab: `name_word_count` drops a single-use local. - Comments: decision blocks trimmed to what the code does, the measurement and the reason; the `Dr. Smith, Ed` / `Xyz. Smith, Ed` divergence is told once, at `is_title_shaped`; two stale reader rosters corrected; three notes about a comment's previous wording removed. Declined: moving `own_words` into `_vocab` -- mechanisms.md#ONE-PREDICATE-PER-QUESTION puts a predicate over token roles in `_pieces`. decisions.md#S2's open follow-up now cites #531. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 19, 2026
derek73
added a commit
to IMGillusion/python-nameparser
that referenced
this pull request
Sep 22, 2026
rules.md#M2's statement gains the reader and the reason behind the credential stop commit 1 put in it: the double check stated once for both forks -- the count of words to spare includes the very words the marker removes -- and the reader named, the trailing rule where a trailing rule reads the part (no comma, and before a SUFFIX comma, measured to read the same way), the end of the given part after a family comma, nobody before that comma or past a second one. The lone-word floor is stated as the deliberate divergence it is from the `née V` / `née PhD` precedent, with the reason: that class carries no evidence of which it is. Reporting is stated at the boundary the tree actually holds -- a member ENDING a clause some rule reads is reported where the clause KEEPS it, while one it gives up reports only where the position it lands in reports, which `Doe, Dr. nee Smith MA` and `Berg, abdul nee Jones MA` would have falsified as a universal. #S2 and #S3 gain the slot in their enumerations; #P6 needs no change, the `do` reading here being derek73#531's unchanged. A second Accepted row records the trailing-title boundary, where the two spellings disagree. Its two example lines were already corpus names, so corpus_rules.jsonl grows by two and no ledger claim moves. decisions.md gets one bullet under M2 amending the 2026-08-22 derek73#424 entry -- which is left exactly as it landed -- and one under S2. The first records the double check, the reader table, the clamp and the two names a veto got wrong, the `do` pair and the accepted costs; it also re-measures the `one_case` plumbing those sites carry, which the 2026-09-18 entry recorded as inert under the numeral-only reading. The pair is the finding: 0 over the corpus as it stood, 36 on six names over the corpus with this change's own rows, the plumbing live either way. The second records the shared predicate, its frame price, and the one-case-head exception as the M2 instance of derek73#492's deferred question. The release log gains one bullet. One correction in place: the derek73#530 bullet said "the one slot this bullet left silent", which two bullets now close rather than one. docs/customize.rst's two 2.4 switch entries enumerate the positions each switch reaches, so both gain this slot. Three sweep findings beyond the plan's table, each a claim no test reads. The 1.4.0 ledger's fix(derek73#424/derek73#445) prose quoted the superseded Accepted row and said the fork is left to assign; it now says the WRITING declines the word. test_parser.py's "the walk takes the numeral only" is false of the tree, and the row under it is really about the member not being TRAILING, so it says that and gains the mirror case. And the judged-token sentence test_properties.py attributes to mechanisms.md is decisions.md#S2's, while the P3 sentence the same comment leans on says something P3 does not say -- both corrected to what those documents carry. mechanisms.md gains a field note for the trap commit 2 hit: a ledger rule EXPLAINS a diff and nothing checks that its sentence still DESCRIBES it, so a too-wide anchor kept `unexplained: 0` green over a name that had started reading the opposite way. Attribution against the parent found it; the gate could not. Review round: the design-docs review found a MOVER that reports nothing -- `Jane Doe, Jr nee Smith MA`, where the take leaves a post-nominals-only segment that is read whole -- which is the pre-existing no-name-word-in-front silence, written as a title's and reached by a post-nominal too; stated in M2 and S2, widened in _types.py, added to the M2 bullet and the release note, and pinned by a unit test rather than an example line, the name differing from this tree at all five baselines for reasons mostly not this change's. M2 and P6 now cite each other. The two _group.py denominators are re-measured: 36 of 10,752 (1,792 names) and 0 over 21,504, the latter with the probe shown live (site reached 394 times, tag admits 310). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
derek73
added a commit
to IMGillusion/python-nameparser
that referenced
this pull request
Sep 22, 2026
…nd the ph removal is on the record Maintainer fix-up on PR derek73#521 after the merge from master, the eight items of the 2026-09-16 review comment: - decisions.md R4: the reach is remeasured on the merged tree with the recipe's comparator named (master's `_cap_word` at 23e52dc), and the two earlier snapshots are explained rather than replaced -- the `ph` removal took 13 forced movers back to `Ph. D.`, and the rows PRs derek73#530/derek73#532/derek73#534 added account for the rest of the drift. The exceptions map's job is stated as the spellings `str.capitalize()` gets wrong, not "non-all-caps" (II/III/IV are all-caps); the precedence over Mac/Mc and the role-not-tag reach of the gate are recorded. - decisions.md: an `Excluded (SUFFIX_ACRONYMS — ph)` block beside esq's, so a wordlist sweep does not put the fragment back. - rules.md R4: the non-acronym clause is qualified by the exceptions map (`john smith ii` -> `II`), the acronym repair's precedence over the Mac/Mc convention is stated and pinned by a `john smith mcse` row (`McSe` without it), and the Accepted paragraph names which clause it is about and states the acronym repair's contrast on a spliced suffix. - release_log.rst: the bullet moves from the shipped 2.3.0 section to 2.4.0 with the current digits, and `ph` leaving the set gets its own bullet in the rai/cha shape. - corpus_rules.jsonl regenerated (three new R4 rows). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #289, closes #516
A bare ambiguous credential acronym is read by the evidence the writing carries, not by position alone.
#289: written case, switch-free, listed set only
Jack MAMAMAJohn Smith MaMaSmith, familyMaSmith, MAMASmith, suffixMAJohn Smith, MAMA, familyJohn SmithJohn, familySmith, suffixMA(1.4.0 restored)John Smith, Ed,john smith, ma,JOHN SMITH, MAJOHN SMITH MA,ANH DO,jack ma,Jack Ma,毛泽东, MAA name written wholly in one case carries no contrast and keeps the positional rule, and a member written wholly in lowercase carries no lean. At a comma the words-to-spare count is of NAME words and decides first, so
Smith Jr., MAkeeps its family; the lean is read only where the count leaves the word a name.#516: two Policy switches with different defaults
unlisted_dotted_suffixes(default True): a token of two or more alphabetic period-separated chunks that no vocabulary claims joins the class by shape, and position decides.John Smith X.Y.Z.gives suffix,Jack X.Y.Z.keeps its family, both reported. The roman-chunk accident retires narrowly whether or not the switch is on, soJack X.Y.I.reads family again whileMsc.Ed.,JD.CPA,Lt.Gov.andJ.씨keep their readings.unlisted_caps_suffixes(default False): the same for an all-caps word found in no wordlist, in a mixed-case name. Opt-in becauseJean Pierre DUPONTgives familyPierre, suffixDUPONTwith it on, and a swallowed family name is the worse failure. Two-wordJean DUPONTandMinjun KIMkeep their family either way.Reports. No new
AmbiguityKind. Every decision at these slots emitsSUFFIX_OR_NAME, and the comma's own decision about such a word (credential run or given name) is reported for the first time. The attachment fork after a family comma,Berg, Jan vd, already reported. One report goes away:Steven Hardman, MD, DO, DDSstops reportingcomma-structure.Accepted costs, recorded at
decisions.md#S2.Freiherr von Berg MAmoves to familyvon Berg, suffixMA.abdul Smith Jr MareadsJras a middle name, since the surname lean stops the peel before the suffix behind it.Decisions made during execution, for your review. Each is a dated bullet in
decisions.md#S2.마틴 킹, MAand田中 太郎, MAread suffixMAagain, as 1.4.0 did.毛泽东, MAis unmoved.Smith, ma,毛泽东, MAandSmith, MA PhDeach report once.Smith Jr., A.B..1.4is not an acronym, and the shape is refused in scripts with no period abbreviations, soJohn Smith 田.中.keeps its family.John Smith, LEED AP) is the caps class's alone.Shape of the change. One fact promoted to
ParseState.one_case, one own-words helper sharing classify's marker tagger, one lean predicate read at three sites, and one tag for a claim that comes from the writing rather than the vocabulary.Ten commits. Six build commits: the prerequisite, the lean, the dotted switch, the all-caps switch, rules.md with the corpora and the five ledgers, and the design and release record. The three behavior commits are deliberately red on the ledger digest guard and on the rules.md example lines they move; the ledger commit is the recovery point. Four review commits follow, all green.
Whole-PR review round. Five reviewers went over the finished branch, and two more verified the fixes. What changed as a result:
suffix-or-namereport is restored where a particle chain absorbs an acronym the lean declined.John van der Berg Mahad gone silent.Kim김민준씨, MApeels its honorific the wayKim김민준씨, PhDdoes.comma-structurereport (John Smith, MD, R.A.I.).Policyfields moved to the end of the dataclass, so positional 2.3 calls keep their meaning.Recorded rather than changed, in
decisions.md#S2: digit-dotted tokens such asJohn Smith 1.4.2move out of the suffix reading silently, and the comma report covers the first word after a family comma but not the trailing slot of the given part. That slot is a 2.0-era reading this PR does not move (Doe, John MAreads middleMA; 1.4.0 read suffix), and it is recorded as open.Verification. Full suite green, mypy and ruff clean, frame count unchanged on the reference name with
_CALL_BASELINEuntouched, and the differential at 1.4.0, 2.0.0, 2.1.0, 2.2.0 and 2.3.0 with 0 unexplained. Seven radar rows at 2.3.0 are this change's own unclassifiedsuffix-or-namereports.🤖 Generated with Claude Code