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
9 changes: 5 additions & 4 deletions AGENTS.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/design/decisions/A1-ambiguity-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
- A report whose fork the rest of the parse resolved to neither branch is withdrawn in assemble, the one place that sees final roles: a connective-or-initial letter roled suffix or title loses that report and keeps its own, so `JOHN QUINCY SMITH I` reports `suffix-or-name` alone — 2026-09-20 #397.
- The decision stays at its emitter and assemble words the field from the word's final role (`PendingAmbiguity.field_tail`), so a report names the field its word lands in whatever rule moved it: `, Ma Dr.` reports 'Ma' "read as a family name", and `Kim Min Do` under FAMILY_FIRST reports 'Do' read as a family name; a placeholder in the detail was declined — 2026-10-08 #626.
- A report on a part past the second comma names no field: `John Smith, Jr., Dr. Bart` reports "segment 'Dr. Bart' beyond the recognized comma structures; read best-effort"; naming every field the part's words land in was declined — 2026-10-10 #629.
- The listed-member report after a family comma names the role the comma binds, worded at the emitter: `John, Ma.` reads title 'Ma.' and reports "read as a title" — 2026-10-21 #793.
- The listed-member report after a family comma names the role the comma binds, worded at the emitter: `John, Si.` reads title 'Si.' and reports "read as a title" (its example was `John, Ma.` until decisions/H2 made `Ma.` there a given name written short) — 2026-10-21 #793.

Elsewhere: P8's "connects nothing", withdrawn once over final roles in assemble, is decisions/S10's 2026-10-18 #722's /simplify pass entry.

Expand Down
8 changes: 7 additions & 1 deletion docs/design/decisions/H2-leading-abbreviation-title.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
- An abbreviation of two or more letters ending in its one period, opening the part that carries the given name (the whole name, or the part after a family comma), is a title even unlisted and even where it is suffix vocabulary, and a single-letter initial is not: `Insp. Jane Morse` → title 'Insp.', `Morse, Det. Insp. Jane` → title 'Det. Insp.', `Esq. Smith` → title 'Esq.', `J. Smith` → given 'J.' — 2026-06-30 #288.
- The shape is an unbroken run of letters, so an unlisted abugida abbreviation stays a name word and only vocabulary recognizes it — 2026-06-30 #288.
- The shape declines a period-marked word carrying a script with no initials: `田中. 太郎` → family '田中.', where `Smith. John` keeps title 'Smith.' — 2026-09-10.
- C13 wins for a credential opening the part after a family comma (`Smith, Esq. John` → suffix 'Esq. John'), and the shape still reads a title there for a word that starts no S8 run (`Smith, Insp. John`, `Smith, Ma. John` → title) — 2026-10-20 #761.
- C13 wins for a credential opening the part after a family comma (`Smith, Esq. John` → suffix 'Esq. John'), and the shape still reads a title there for a word that starts no S8 run (`Smith, Insp. John`, `Smith, Do. John` → title) — 2026-10-20 #761; its `Smith, Ma. John` example moved to the given name on 2026-10-26 #789.
- A given name written short outranks the shape: a word the vocabulary lists with a `given` reading whose `same_as` is the full name, period-marked where the shape would fire, is the given name and the name reads as it would with the full name there (`Chas. Smith` → given 'Chas.', `Mrs Ma. Liza Cruz` → title 'Mrs', given 'Ma.'). The shipped set is the traditional English abbreviations and the Filipino `ma` and `jo`; a listed title still wins, and the reading acts nowhere else — 2026-10-26 #789.

Elsewhere: #316's question 2, a symmetric leading rule reading `Esq. Smith` as a suffix, is declined and the trailing slot reads vocabulary, decisions/H5's 2026-09-08 #316 entry (the undated `Decided 2026-09-08` paragraph below records the hook it closed here); the shape does not fire before a family comma, decisions/H6's 2026-10-17 #701 and 2026-10-18 #710 entries; a letter typed decomposed is the same letter to the shape, decisions/nfd-shapes' 2026-10-12 #652 entry, and the script veto reads the composed spelling, its 2026-10-13 #665 entry; halfwidth katakana is classified since #594 (decisions/W4).

Expand All @@ -22,3 +23,8 @@ Decided 2026-09-08 (was Open: [#316](https://github.com/derek73/python-nameparse
- 2026-09-10 — the shape declines a word carrying a script with no initials (#323); the argument, the halfwidth-kana limit and the measurements are in #cjk-full-stops. That limit was closed on 2026-10-03 by #594, which classifies halfwidth katakana (decisions/W4).

- 2026-10-20 (Derek), #761 — C13 WINS OVER H2 FOR A CREDENTIAL OPENING THE PART AFTER A FAMILY COMMA. The H section's skeleton migration (PR #779) found the two rules each claiming `Smith, Esq. John`: rules/H2 made an abbreviation opening the part after a family comma a title "even when the word is suffix vocabulary", with an exception only for a part that is nothing but suffix words (C8), while rules/C13 makes a credential opening that part the postnominal part however it goes on. The parser already read it C13's way, suffix 'Esq. John' with `suffix-or-name` under all three orders, and neither rule said so. Derek decided C13 wins, with no behavior change; rules/H2 gains the Precedence bullet and its Then names the exception. What the win covers was measured over the suffix vocabulary, each alphabetic word of two or more letters written title-case with a period in `Smith, <word> John` (2026-10-20, py3.11, the tree at #779): 666 words read as the postnominal part, and 22 still read as a title by H2's shape — the 12 title/suffix duals (`Cpl.`), 7 ambiguous acronyms (`Ma.`, `Do.`) and `Abd.`, `Mc.` and `Vd.` — none of them a word that starts S8's run. So the bullet is scoped to C13's own words rather than to every listed suffix word, which Derek confirmed once shown the 22 (keeping the parse unchanged), and `Smith, Ma. John` is an example beside `Smith, Esq. John` and the unlisted `Smith, Insp. John`.

- 2026-10-26 #789 (#752, phase 2k) — A GIVEN NAME WRITTEN SHORT OUTRANKS THE SHAPE. The traditional English abbreviations of given names (`Chas.` Charles, `Thos.` Thomas, `Jas.` James, `Geo.` George, `Robt.` Robert, `Benj.` Benjamin, `Jno.` John, `Saml.` Samuel, `Edw.` Edward, `Richd.` Richard, `Wm.` William) and the Filipino `Ma.` (María) and `Jo.` (José) opened the part carrying the given name as titles by the shape, from 1.4.0 through 2.6.0 (checked against the 1.4.0, 2.0.0, 2.3.0 and 2.6.0 wheels: `Chas. Smith` → title 'Chas.', `Ma. Cristina Reyes` → title 'Ma.', given 'Cristina'), and a reader of either would not hesitate: each is the given name. Agreed by Derek on 2026-10-23 as part of #752's design, decisions/vocabulary-model's entry of that date. Each word takes a `given` reading whose `same_as` is the full name, which compiles it into `GIVEN_NAME_ABBREVIATIONS` (`Lexicon.given_name_abbreviations`), and the shape declines a word in it: a vocabulary reading outranks a reading a shape rule derived, the precedence the vocabulary model allows a language pack and applies here in the default. The precedence is the shape's alone. A listed title is asked before the shape and still wins, so a caller who lists `chas` as a title gets the 1.4 reading back; and nothing else reads the set, so the bare word (`Ma Smith`, `Smith, John Ma`, `John Smith MA`) and the dotted word anywhere but the head of the given-name part (`John Smith Ma.` → family 'Ma.', `John Ma. Smith` → middle 'Ma.') read as they did, `ma` keeping its surname and credential readings.
- **What the name reads as.** Wherever the shape read the abbreviation as a title, the name now reads, field for field, as it does with the plain given name `Jack` in the abbreviation's place, its case matched, and wherever the shape read none, as it did: `test_a_given_name_written_short_reads_as_a_given_name` (tests/v2/test_properties.py) holds that for each shipped word in its three period-marked spellings, in the 20 of its 21 slots where the shape or the comma's count reads one, and holds the three bare spellings to the set-emptied reading in all 21, under each of the three orders. One reading is not the full name's: rules/C6's case contrast skips a period-marked word, so `Chas. SMITH, XYZ` reverses (given 'XYZ', family 'Chas. SMITH') as `J. SMITH, XYZ` does and as it did before, where `Charles SMITH, XYZ` reads suffix 'XYZ'; left as it is, the contrast's question being C6's (found by the second review). So under a family-first order `Chas. Smith` reads family 'Chas.', given 'Smith', as `Jack Smith` does: the declared order places the word, which the shape had kept out of every name field. The comma moves too, since rules/C4 counts the name words before a comma by asking the shape: `Chas. Smith, Ed` reads given 'Chas.', suffix 'Ed', as `John Smith, Ed` does, where `Chas.` had counted as a title and the name reversed (given 'Ed', family 'Chas. Smith'). The bare spellings read as they did in every slot of that test, a capitals one behind a comma included (`John Smith, JAS` keeps suffix 'JAS'): its first version had put the set in the wordlist rosters the capitals shape and the name-contrast test read, which reversed that name and `Jas SMITH, XYZ` until the code review found it.
- **Measured** against master 12384fae (2026-10-26), with `snapshot.py` for the committed snapshot, `cldr_agreement.py` for the agreement views, `snapshot.py --local <corpus> --base <master checkout>` for ctgov-officials, fec-individuals and tse-donors, and `local_agreement.py psc-individuals --base <master checkout>`: the committed snapshot moves 2 names, `Ma.` opening the name and rules/H2's own example `Smith, Ma. John`, now given 'Ma.'; the CLDR, GND and Wikidata agreement views do not move, and the conventions view gains its one `Ma.` rendering's title. ctgov-officials moves 15 of 536,981 officials, each `Ma.` opening the name in mixed case; fec-individuals moves 24 of 1,893,964 names, each written in capitals after a family comma (`WM.` 20, `MA.` 2, `GEO.` 1, `EDW.` 1); tse-donors moves 2 of 854,531 pairs, `MA.` opening the name. psc-individuals, scored against the fields its filers typed, has 86 records fixed, 0 broken and 2 changed, all 88 `Ma.` opening the forename box: 81 behind a salutation filed in the title box (#853's shape, `Mrs Ma. Liza …`), 7 with no title. The spike of 2026-10-24 counted the same.
- **Vetting**, recorded on each word in en.toml and fil.toml: `tools/name_usage.py` counts each as a given name in US SSA data (Chas 3,223, Wm 2,736, Geo 1,324, Robt 468, Thos 166, Jas 124, Jno 11, Edw 6 births, summed over the years; `Benj`, `Saml` and `Richd` under the source's floor), and none as a credential in NPPES. `Jas` is also a surname (117 bearers in the 2010 US Census) and `Jo` a given name of its own (180,911 US births) and a Korean surname, and `Ma` a Chinese surname and a listed credential; a period-marked word opening the given part is a given name on each of these readings, and the credential reading had never taken it there, the shape reading a title first. `tools/vocab/query.py --word` found no other reading on any of the thirteen but `ma`'s and `wm`'s refused title.
10 changes: 8 additions & 2 deletions docs/design/decisions/vocabulary-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ The vocabulary was a set of base sets plus marker subsets (`particles` and `part
- Every language file is in build-checked order (kind, then the `same_as` path from its root head, then the codepoints of the text), the check naming the entry to move, running last, and refusing a `same_as` loop of any length; `und.toml` is exempt — 2026-10-19 #747; 2026-10-21 #762.
- The particles take eight kinds beside the generic one, `expands` carrying a particle's gloss and `note` its vetting, and the particle keep-outs are exclusions — 2026-10-19 #749.
- The titles take ten kinds beside the generic one, `academic` and `occupation` divided by function rather than subject, and the title keep-outs are exclusions — 2026-10-19 #750, title kinds; 2026-10-19 #750, the rest of the titles.
- `wm` is no title: William's abbreviation reads as the given name it is (`Wm Smith` → given 'Wm'), and its title reading is refused in en.toml. The dotted `Wm.` opening the given part is still rules/H2's title; a given reading that outranks H2 belongs to phase 2 (#752) — 2026-10-22 #789.
- `wm` is no title: William's abbreviation reads as the given name it is (`Wm Smith` → given 'Wm'), and its title reading is refused in en.toml — 2026-10-22 #789. The dotted `Wm.` opening the given part reads given too, by the reading below — 2026-10-26 #789.
- A given name written short is a `given` reading whose `same_as` is the full name, normalized and naming no entry, a `family` reading taking none; the word compiles into `GIVEN_NAME_ABBREVIATIONS` (`Lexicon.given_name_abbreviations`), which outranks rules/H2's shape and nothing else (decisions/H2). The traditional English abbreviations in en.toml (`chas`, `wm`) and the Filipino `ma` and `jo` in fil.toml carry one — 2026-10-23 #752; 2026-10-26 #789, phase 2k.
- Abbreviations and full words spelled alike across European languages (`dr`, `prof`, `doctor`, `professor`, `docent`) are in `mul.toml`; a credential goes to a file only on evidence that names in that language carry it, so none is in `mul.toml` — 2026-10-19 #750, the rest of the titles; 2026-10-20 #751, the credentials.
- `und.toml` holds only `bon` and `dí`, particles of unrecorded origin; every other word, the credentials, conjunctions, bound given names and birth markers included, is in a language file or in `mul.toml` — 2026-10-19 #749; 2026-10-20 #751, the conjunctions.

Not standing: the plans the classifications carried out, phase 1's mechanical conversion of the unclassified categories into `und.toml` (2026-10-18 #737) and the shared readings left in place until their categories were classified (2026-10-19 #749), both done by 2026-10-20 #751, the conjunctions; and #747's reason for exempting `und.toml`, its entries keeping the Python lists' order for its vetting comments to point along (2026-10-19 #747), overtaken once it held two entries and no such comment.

Open: #752 (phase 2, derived ambiguity; its sub-phases 2a to 2m, each its own PR, are the 2026-10-23 #752 entry's and the RFC's), #789 (sub-phase 2k: the dotted `Wm.`, `Chas.`, `Geo.`, `Ma.` and `Jo.` opening the given part read given over rules/H2's shape, decided 2026-10-23 #752), #753 (phase 3, language packs), #754 (phase 4, order, shapes and the output model), #766 (whether `bon`, `dí` and three other words stay in the vocabulary).
Open: #752 (phase 2, derived ambiguity; its sub-phases 2a to 2m, each its own PR, are the 2026-10-23 #752 entry's and the RFC's), #753 (phase 3, language packs), #754 (phase 4, order, shapes and the output model), #766 (whether `bon`, `dí` and three other words stay in the vocabulary).

## Log

Expand Down Expand Up @@ -218,3 +219,8 @@ Open: #752 (phase 2, derived ambiguity; its sub-phases 2a to 2m, each its own PR
- **2026-10-26 #752, phase 2i (Derek) — `attaches` MAY NAME A TITLE WORD AS WELL AS A KIND, AND `grace` AND `marshal` JOIN THE CONTESTED TITLES.** Amends the `attaches` bullet of the 2026-10-25 #752, phase 2i entry: a kind reaches every word that later joins it, and once `marshal` became a contested military word the military kind made `Sgt Marshal Smith` a title phrase. A list entry that is no kind must be a word with a title reading (a build check, its mutation in tests/v2/test_vocab.py). `major` attaches to `general` and `sergeant` and `sgt` to `major`. `grace` (style) and `marshal` (military, its #606 exclusion replaced) carry dated `given` readings. The measurement and Derek's answers are decisions/H9's entry of this date.
- **2026-10-26 #752, phase 2j, `wing` — THE FIRST TITLE BATCH: `wing` HAS A DATED `given` READING.** The order is the 2026-10-24 #752 (Derek) entry's. Decision 10 had already read `wing` as a name at the head of the name, so the reading reaches the parts decision 10 left as listed, after a comma and ending the name: `Lau, Wing Kai` reads given 'Wing', and `John Smith Wing.` family 'Wing.'. The rule and the measurement are decisions/H9's entry of this date.
- **2026-10-26 (Derek), #785 — PHASE 2g NARROWED: a capitals member with a name word behind it, and no family comma, does not start the credential's run**, the name word being evidence of initials; `Maria Ana MA Silva`, `Jean Pierre MA DUPONT` and `Mary Jane MA King` keep the readings 1.4.0 through 2.6.0 gave, and `John Smith MA Jones` keeping family 'Jones' is the cost. The record is decisions/S6's entry of this date.
- **2026-10-26 #789, #752, phase 2k — A GIVEN NAME WRITTEN SHORT IS A `given` READING WITH `same_as`, AND IT OUTRANKS rules/H2's SHAPE.** Carries out item 14 of the 2026-10-23 #752 entry above and the second half of #789; the first half, bare `wm` out of the titles, is the 2026-10-22 #789 entry. SUPERSEDES: in the README's property table, `same_as` as a property of every category but `name`. What changes in the vocabulary:
- A `given` reading may carry `same_as`, the full given name the word abbreviates (`chas` is `charles`). On a name reading it names a name, not an entry, so check 7 asks only that it be normalized and not the word itself, and a `family` reading is refused one. The reading compiles the word into a new set, `GIVEN_NAME_ABBREVIATIONS` (`Lexicon.given_name_abbreviations`, re-exported from `nameparser.config.given_names`), so an entry holding only such a reading is not the inert name reading the build warns of. No `Constants` attribute reaches it, and the shim passes it whole: a v1 caller who lists the word as a title has it read as one, the leading peel asking the title vocabulary before the shape.
- The set's one reader is rules/H2's shape test, which declines a word in it, so the vocabulary reading outranks the shape-derived one, decision 20 applied in the default. It is not a derived marker: no second vocabulary reading is weighed, only the shape's. `ma`, which already had given, family and credential readings in en.toml, takes its abbreviation reading in fil.toml, and the credential's ambiguous marker is unchanged, its name readings already deriving it. `jo` had no reading before, and its `given` reading derives nothing.
- The words, with their counts on each entry: `benj`, `chas`, `edw`, `geo`, `jas`, `jno`, `richd`, `robt`, `saml`, `thos` and `wm` in en.toml (the last keeping its refused title, whose reason now names this reading), `jo` and `ma` in fil.toml. What moved, the vetting and the grid are decisions/H2's entry of this date. Recompute the list: `uv run python -c "from nameparser import Lexicon; print(sorted(Lexicon.default().given_name_abbreviations))"`.
Adding the field changes `Lexicon`'s pickle layout, as phases 2h and 2i did.
Loading
Loading