Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions AGENTS.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ Open: none in this file.
- 2026-10-04 (Derek), #603 — A credential opening the part after the comma makes it the postnominal part, whatever follows. The record moved to decisions/C13 with that clause (2026-10-19).
- 2026-10-18 #728 — SPLIT FROM decisions/C1 with the rule. The entries above were written under decisions/C1 while this rule was part of rules/C1, and moved here unchanged but for the pointers the move broke, the measurement paragraphs, each cut to one line naming its population, counts, baseline and PR, and the superseded passages, each cut to its decision and what replaced it; where one says rules/C1 or C1, it means the rule as it then stood, which held this one.
- 2026-10-19 — RULE SPLIT: a credential opening the part after the comma left rules/C8 for rules/C13, one rule per piece of evidence (docs/design/AGENTS.md); C8 keeps the part with no name word and the part that is nothing but suffix words. The #603 entry moved to decisions/C13, a cross-reference standing in its place. Where the entries here or elsewhere say rules/C8 of the opened part (the #613 and #544 entries in decisions/C1 among them), that piece is rules/C13's now.
- 2026-10-25 #857 — `sa` leaves the vocabulary: its military reading (Seaman Apprentice, a title) and its credential reading are both refused on the word (`excluded`), superseding the 2026-08-23 entry's `sa` half and decisions/suffix-acronym-collisions' 2026-10-21 held-out entry. It reads as any name word does, whatever the case, because the Portuguese surname Sá written without its accent is the one bearer the corpora show. The path to it: marking `sa` ambiguous (`may_be_name`) fixed `Maria de Sa` but left three costs, and the evidence for each reading it was keeping came back empty. (1) A one-case name ending in `SA` still read a suffix (S6), so all 255 SÁ / SA pairs of tse-donors (#843) still parted. (2) The title reading took the slot in front of a name and alone after a family comma, which `ma` does not (`Smith, Sa` → title 'Sa' where `Smith, Ma` → given 'Ma'; `Smith, John PhD Sa` → title 'Sa', suffix 'PhD', unreported). (3) Every name read with `Sa` as a title in the committed and eight local corpora is a person whose given name is Sa (`Sa Liu`, `Sa Mahammed Ilyas`) or the Arabic Sa ad (`Sa ad Hariri`), or whose Portuguese surname Sá is written without its accent (`Sa Pinto`), none a rank; and every SA or S.A. suffix is a company (`Galderma S.A.`, `Novartis Biociências SA`), a South African qualifier (`FCP(SA)`), or initials typed without stops (`MANN, S.A.`, `BROWN, MARYAM SA`) — no person writes it as a credential, the 167 NPPES providers aside, whom `name_usage.py` counts and nobody has read by item. Readings now: `Maria de Sa`, `MARIA DE SA`, `maria de sa` → family 'de Sa'/'DE SA'/'de sa' (was family 'de', suffix 'Sa'/'SA'/'sa' since 1.4.0); `Joao Sa`, `ANA SA`, `ANA SILVA SA` → family 'Sa'/'SA'; `SA Smith` → given 'SA', family 'Smith'; `Smith, SA` → given 'SA' (was suffix 'SA', #296's audit row); `Mrs Sa Li` → title 'Mrs', given 'Sa' (the second title word is gone). Accepted: a credential `SA` after a mixed-case name is a name word, so `John Smith SA` reads middle 'Smith', family 'SA' (rules/S9 admits an unlisted all-caps word as a credential by shape only behind a comma, and this one has no vocabulary behind it); and so are the comma shapes, the same reading an unlisted two-letter caps word gets (`John Smith, XY`): `John Smith, SA` → given 'SA', family 'John Smith' (the name merged into the family, where 1.4.0 through 2.5.0 read given 'John', family 'Smith', suffix 'SA'), `John Smith, SA, PhD` → family 'John Smith', suffix 'PhD', `Smith, John SA` → middle 'SA', and `, SA` → given 'SA' (1.4.0 read title 'SA'; 2.5.0 suffix 'SA'). The corpora hold 15 such after-comma names in ctgov-officials and 10 in fec-individuals (`Spector, SA` went suffix → given 'SA'), and NPPES counts 167 US healthcare providers who write it, none read by item: if they turn out to be a credential, that is the evidence to restore it on. `Smith, John PhD Sa` keeps suffix 'PhD Sa' and reports SUFFIX_OR_NAME; `John Smith S.A.` and `Smith, S.A.` go through the unlisted-dotted rule and report SUFFIX_OR_NAME; a parenthesised `(SA)` after a credential, ClinicalTrials.gov's `FCP (SA)`, is a nickname 'SA' where it was inside the suffix (25 names in ctgov-officials). Local corpora, `snapshot.py --local` against the base 8c965d74 (2026-10-25): tse-donors moves 1,613 of 848,351 names, about 700 gaining the `SA` as part of the family name (`ADAO DE SA FERREIRA` → family 'DE SA FERREIRA', was family 'DE', suffix 'SA FERREIRA'; `WESLEY VITOR SA PEREIRA` → family 'PEREIRA'), and `local_corpora.py pairs tse-donors --agreement` reads 0 accent-only pairs with two surnames where the base read 255 SÁ / SA; ctgov-officials 54 of 352,104, 25 of them the `(SA)` nickname; psc-individuals 40 of 1,034,888 (three `Mrs Sa Li`-shaped names lose a title); ukec-individuals 0. Putting a reading back is cheap — add it and delete the matching `excluded` entry, which the build checks — but the form matters: a `credential` reading WITH `may_be_name` returns the costs the path above ended on (255 parting pairs, `Smith, Sa` reading a title once `military` is back), and one without it returns `Maria de Sa` reading suffix. A caller who needs `SA` as a credential adds it to their own lexicon.
- 2026-10-25 #857 — `sa` leaves the vocabulary: its military reading (Seaman Apprentice, a title) and its credential reading are both refused on the word (`excluded`), superseding the 2026-08-23 entry's `sa` half and decisions/suffix-acronym-collisions' 2026-10-21 held-out entry. It reads as any name word does, whatever the case, because the Portuguese surname Sá written without its accent is the one bearer the corpora show. The path to it: marking `sa` ambiguous (`may_be_name`) fixed `Maria de Sa` but left three costs, and the evidence for each reading it was keeping came back empty. (1) A one-case name ending in `SA` still read a suffix (S6), so all 255 SÁ / SA pairs of tse-donors (#843) still parted. (2) The title reading took the slot in front of a name and alone after a family comma, which `ma` does not (`Smith, Sa` → title 'Sa' where `Smith, Ma` → given 'Ma'; `Smith, John PhD Sa` → title 'Sa', suffix 'PhD', unreported). (3) Every name read with `Sa` as a title in the committed and eight local corpora is a person whose given name is Sa (`Sa Liu`, `Sa Mahammed Ilyas`) or the Arabic Sa ad (`Sa ad Hariri`), or whose Portuguese surname Sá is written without its accent (`Sa Pinto`), none a rank; and every SA or S.A. suffix is a company (`Galderma S.A.`, `Novartis Biociências SA`), a South African qualifier (`FCP(SA)`), or initials typed without stops (`MANN, S.A.`, `BROWN, MARYAM SA`) — no person writes it as a credential, the 167 NPPES providers aside, whom `name_usage.py` counts and nobody has read by item. Readings now: `Maria de Sa`, `MARIA DE SA`, `maria de sa` → family 'de Sa'/'DE SA'/'de sa' (was family 'de', suffix 'Sa'/'SA'/'sa' since 1.4.0); `Joao Sa`, `ANA SA`, `ANA SILVA SA` → family 'Sa'/'SA'; `SA Smith` → given 'SA', family 'Smith'; `Smith, SA` → given 'SA' (was suffix 'SA', #296's audit row); `Mrs Sa Li` → title 'Mrs', given 'Sa' (the second title word is gone). Accepted: a credential `SA` after a mixed-case name is a name word, so `John Smith SA` reads middle 'Smith', family 'SA' (rules/S9 admits an unlisted all-caps word as a credential by shape only behind a comma, and this one has no vocabulary behind it); and so are the comma shapes, the same reading an unlisted two-letter caps word gets (`John Smith, XY`): `John Smith, SA` → given 'SA', family 'John Smith' (the name merged into the family, where 1.4.0 through 2.5.0 read given 'John', family 'Smith', suffix 'SA'), `John Smith, SA, PhD` → family 'John Smith', suffix 'PhD', `Smith, John SA` → middle 'SA', and `, SA` → given 'SA' (1.4.0 read title 'SA'; 2.5.0 suffix 'SA'). The corpora hold 15 such after-comma names in ctgov-officials and 10 in fec-individuals (`Spector, SA` went suffix → given 'SA'), and NPPES counts 167 US healthcare providers who write it, none read by item: if they turn out to be a credential, that is the evidence to restore it on. `Smith, John PhD Sa` keeps suffix 'PhD Sa' and reports SUFFIX_OR_NAME; `John Smith S.A.` and `Smith, S.A.` go through the unlisted-dotted rule and report SUFFIX_OR_NAME; a parenthesised `(SA)` after a credential, ClinicalTrials.gov's `FCP (SA)`, is a nickname 'SA' where it was inside the suffix (25 names in ctgov-officials). Local corpora, `snapshot.py --local` against the base 8c965d74 (2026-10-25): tse-donors moves 1,613 of 848,351 names, about 700 gaining the `SA` as part of the family name (`ADAO DE SA FERREIRA` → family 'DE SA FERREIRA', was family 'DE', suffix 'SA FERREIRA'; `WESLEY VITOR SA PEREIRA` → family 'PEREIRA'), and `local_corpora.py pairs tse-donors --agreement` reads 0 accent-only pairs with two surnames where the base read 255 SÁ / SA; ctgov-officials 54 of 352,104, 25 of them the `(SA)` nickname; psc-individuals 40 of 1,034,888 (three `Mrs Sa Li`-shaped names lose a title); ukec-individuals 0. Putting a reading back is cheap — add it and delete the matching `excluded` entry, which the build checks — but the form matters: a `credential` reading WITH `may_be_name` returns the costs the path above ended on (255 parting pairs, `Smith, Sa` reading a title once `military` is back), and one without it returns `Maria de Sa` reading suffix. (Corrected 2026-10-25, #752: the marker is now derived, so `sa`'s `family` and `given` readings mark a `credential` reading put back, and `may_be_name` is a build error; the unmarked form would need those counts moved into the reading's `note`, as `ld`'s are.) A caller who needs `SA` as a credential adds it to their own lexicon.
2 changes: 1 addition & 1 deletion docs/design/decisions/ma-do.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Standing

- `ma` and `do` are members of the ambiguous acronym set (`suffix_acronyms_ambiguous`: credential readings with `may_be_name`, `uv run python tools/vocab/query.py --word ma`), kept there because both are common surnames; the set has grown past these two since (decisions/suffix-acronym-collisions), and the marking is still what lets `Jack Ma` read family 'Ma' with `suffix-or-name` reported, while `John Smith MA` reads suffix — 2026-07-17.
- `ma` and `do` are members of the ambiguous acronym set (`suffix_acronyms_ambiguous`: acronym readings on a word with a `given` or `family` reading, decisions/vocabulary-model 2026-10-25, `uv run python tools/vocab/query.py --word ma`), kept there because both are common surnames; the set has grown past these two since (decisions/suffix-acronym-collisions), and the marking is still what lets `Jack Ma` read family 'Ma' with `suffix-or-name` reported, while `John Smith MA` reads suffix — 2026-07-17.
- In a name written in more than one case, a member in capitals leans credential and is taken with nothing to spare (`Jack MA`, `Jack DO` → given 'Jack', suffix 'MA'/'DO'), where `Jack Ma` keeps family 'Ma'; a deliberate break from v1, which read `Jack MA` as family 'MA' — 2026-09-15 #289.
- A member written with its periods, one after each letter, counts unambiguously (`Jack M.A.`, `Jack D.O.` → suffix, `given-or-family` reported when only the given name remains), and one trailing period is no such spelling (`Jack Ma.` → family 'Ma.') — 2026-07-17.
- A parenthesized bare `(MA)` or `(DO)` reads as a nickname, no longer escaping to suffix as in 1.x, and reports `suffix-or-nickname` — 2026-07-17.
Expand Down
4 changes: 2 additions & 2 deletions docs/design/decisions/vocabulary-exclusions.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ Excluded (Lexicon.conjunctions — the conjunction readings):

Open (Lexicon.conjunctions — contested membership; the issue is canonical): none. The block held one entry, [#397](https://github.com/derek73/python-nameparser/issues/397) — whether Catalan `i` belongs in the conjunctions at all — answered 2026-09-20 by decisions/P3's bullet of that date: it does, and it joins `conjunctions_ambiguous` in the same change, which was never the contested half. The heading stays with nothing under it on purpose, the same reason an empty ledger roster section is a statement and a missing one is nobody having looked.

Excluded (the never-given / ambiguous particle line, a particle reading's `may_be_given` — #360 owns the vocabulary question):
Excluded (the never-given / ambiguous particle line, a particle's `given` reading, or `may_be_given = false` where it has none — #360 owns the vocabulary question):

- Only 9 of the ambiguous members were individually justified at #360's audit (2026-08); the rest sit there by the conservative default (ambiguous unless argued never-given). #604 (2026-10-04) argued three more on entry — ua, binti, binte — under vocabulary-collisions.
- The audit's scope, as the module comment above the ambiguous particles recorded it until #749 turned the comments into fields: #360 examined "the 12 that appear leading in tools/differential's corpora plus a few more", and left the rest bare rather than record an absence of knowledge as a judgment. Examined is wider than the 9 justified above.
- The per-word reasons are data since #749 (2026-10-19, decisions/vocabulary-model): each member's `note` on its particle reading, in the file of each language whose names it occurs in, and each word kept out (`ben`, `nic`, unaccented `o`, `bt`, `bte`, and the native-script `ال` and `בר`) an `excluded` entry with its reason. `uv run python tools/vocab/query.py --kind particle` lists the members (each word once per file it is in), `--issue 360 --kind particle` the five never-given words #360 added or moved (das, las, los, mc, ste), `--issue 604 --kind particle` #604's five (the never-given ó and ní beside the three above), and `--excluded particle` the refusals; the nine ambiguous members #360 justified carry a `note` but no `issue`, so no query isolates them; a contributor who re-adds a refused word meets the recorded reason as a build error.
- Encoding rationale (#293, predating #360's membership questions): the data layer stores the NEVER-GIVEN set and derives the ambiguous one, because that is safe-by-default for new particles — a one-place addition — and the v1 shim translates by one-directional complement. And the constants are FROZEN specifically to kill the cached-Lexicon.default()-vs-fresh- Constants desync that runtime module-constant mutation caused. The data-layer half is superseded since 2026-10-18 (decisions/vocabulary-model): every particle reading states `may_be_given`, true or false, and neither side is a default; the freeze half stands.
- Encoding rationale (#293, predating #360's membership questions): the data layer stores the NEVER-GIVEN set and derives the ambiguous one, because that is safe-by-default for new particles — a one-place addition — and the v1 shim translates by one-directional complement. And the constants are FROZEN specifically to kill the cached-Lexicon.default()-vs-fresh- Constants desync that runtime module-constant mutation caused. The data-layer half is superseded since 2026-10-18 (decisions/vocabulary-model): from then every particle reading stated `may_be_given`, true or false, so neither side was a default, and since 2026-10-25 a particle may be given exactly where its word has a `given` reading, every other particle reading stating `may_be_given = false`, which still leaves neither side a default; the freeze half stands.
- Load-bearing dependency: TITLES ∩ ambiguous — {do, freiherr, st} until #296's audit, {freiherr, st} since — is what keeps the particle-or-given ambiguity emitter reachable at all; moving them all would leave the shipped vocabulary unable to reach it, which is why test_the_chained_emitter_is_reachable_by_construction (tests/v2/test_parser.py) pins reachability by construction rather than by shipped vocabulary — an empty intersection fails no test and does not mean the emitter is unreachable.

Open (contested vocabulary memberships — the rule is right, the word's set is questioned; the issue is canonical): none. The block held three entries and all three were answered inside a fortnight — #346, #343 and #344 together on 2026-09-06 (see #indic-honorifics) and #342 on 2026-09-07 (see #suffix-acronym-collisions). The heading stays with nothing under it on purpose, the same reason an empty ledger roster section is a statement and a missing one is nobody having looked. sa, se and om (all three since decided, sa on 2026-10-25, #857) are named as the next candidates by #342's own comment and carry no issue, so they are not entries here.
Expand Down
Loading
Loading