diff --git a/docs/design/decisions/M4-maiden-marker-makes-the-lone-name-word-the-family.md b/docs/design/decisions/M4-maiden-marker-makes-the-lone-name-word-the-family.md index 8ba750b98..421b79ab1 100644 --- a/docs/design/decisions/M4-maiden-marker-makes-the-lone-name-word-the-family.md +++ b/docs/design/decisions/M4-maiden-marker-makes-the-lone-name-word-the-family.md @@ -4,7 +4,8 @@ - A maiden name beside exactly one name word makes that word the family name, under every name order: `Smith née Jones` → family 'Smith', maiden 'Jones', where through 2.1 it read given 'Smith' with the family empty. The rule is H1's sibling, so a titled name is H1's at both outcomes (`Dr. Jane née Smith` → family 'Jane'; `Sir John née Jones` keeps given 'John') — 2026-08-27 #445 (M4, PR on fix/445-maiden-marked-lone-name). - O4 decides nothing at one name word, so the reading M4 replaces is O5's convention, a guess fixed in advance, and M4 is an exception to it rather than a contradiction of it — 2026-08-27 #445, O4 was SILENT. -- M4 changes only what position decided: a word the vocabulary claims as a given name keeps the reading its position gives it (`abd née Jones` → given 'abd' under the default order, family under either family-first order), and so does a word read as an initial (`J. née Jones Smith V` → given 'J.' by default), both read off tags classify recorded — 2026-08-27 #445, the two carve-outs. +- M4 changes only what position decided: a bound given name keeps the reading its position gives it (`abd née Jones` → given 'abd' under the default order, family under either family-first order), and so does a word read as an initial (`J. née Jones Smith V` → given 'J.' by default), both read off tags classify recorded — 2026-08-27 #445, the two carve-outs. +- A word the vocabulary reads as possibly a given name, without the bound-given claim, is no carve-out and reads as the family name (`Chas. née Jones` → family 'Chas.', `Van née Jones` → family 'Van'), a cost rules/M4 now states; its words, which said "a word the vocabulary has claimed as a given name", were narrowed to the code — 2026-11-05 #815. - M4 counts what the take leaves, not where the marker stood, so the bracketed spelling restores 1.4.0's family (`Smith (née Jones)` → family 'Smith', maiden 'Jones') and the interior spelling is a reading no earlier version gave (`Jane née Jones Smith` → family 'Jane', maiden 'Jones Smith') — 2026-08-27 #445, the two halves. - A nickname holds nothing off: where N3 declines, M4 names the family (`'Smitty' Jones née Smith Jr.` → family 'Jones', suffix 'Jr.', maiden 'Smith') — 2026-08-27 #445, a precedence claim. - `tests/v2/test_parser.py::test_a_maiden_clause_changes_nothing_else` asserts M4's flip over the corpus rather than skipping the names it moves: family takes what given held and every other field stands still — 2026-08-27 #445, the corpus-wide. @@ -22,7 +23,7 @@ Open: none in this file. - 2026-08-27 #445 (M4, PR on fix/445-maiden-marked-lone-name) — Derek's rationale, in his terms: normally if there is only one name we assume it is a given name because we have to pick one, but maiden markers mark a previous surname before marriage, so it would not make sense to include one if there was no other surname for it to clarify — and given that, when a marker leaves only one name word we switch the assumption and read that word as the family name. `parse("Smith née Jones")` reported given 'Smith' with an EMPTY family through 2.1 and reads family 'Smith', maiden 'Jones' since. The rule is written in post_rules as H1's sibling and placed directly under it, so the interaction is decidable by reading rather than by running: where H1 fired there is no GIVEN left for M4 to move, and where H1 declined because the title addresses by given name ("Sir John née Jones") the `not titles` guard keeps M4 off the same word. A titled name is H1's at both outcomes, which is what keeps H1's given-name-title carve-out intact. - 2026-08-27 #445 — the third time in the 2.2 bundle that a name carrying a maiden clause reported no family, and the three share a SYMPTOM rather than a cause. State that carefully, because the first draft of this entry claimed one cause for all three and was wrong. #410 (H1): a title plus one name word reported no family the moment a suffix, nickname or maiden name stood beside it. #411 (P5's reserve): the bound given-name join counted the marker and the maiden name as words it could spend, and spent the family name. Those two ARE one cause -- a count that included words which are no part of the name -- and the grep that would find a fourth is a rule counting name words without first asking which of them are name words. #445 is not that: it changes no count anywhere (post_rules gains a new block, assign gains only a comment), and `parse("Smith")` with no clause beside it at all already read given 'Smith' with an empty family, so nothing was being swallowed. Its cause is the one the next entry gives: O4 decides nothing at one name word, and the reading came from a convention nobody had written down. The site that grep would miss is `_name_positions`'s `count == 1` branch, silent for every order and every name -- which is exactly what O5 now records. - 2026-08-27 #445 — O4 was SILENT at exactly one name word, which is why the shipped reading had no rule to point at and why O5 now exists. O4 reads a name by comparing where its words stand ("the first name word is the given name, the last is the family name"); with one word the first IS the last, so there is nothing to compare and the rule decides nothing. O5 records the reading as the convention it is — a guess fixed in advance so that the same input always reads the same way, not a determination about the word — and names H1, N3 and M4 as the rules that DO decide such a name. Written that way deliberately: a rule asserting "a lone name word is the given name" as a fact would have made #445 a contradiction of the documented behavior instead of an exception to a documented guess, and would make #449 one too. -- 2026-08-27 #445 — the two carve-outs are not inventions, and both rest on mechanisms.md#TWO-LAYER-ASSIGN: the positional layer never overrides a vocabulary claim, and M4 changes only what POSITION decided. A word the vocabulary claims as a given name keeps that reading ('abd née Jones' — `vocab:bound-given`), and so does a word written as an initial ('J. née Jones Smith V' — the `initial` shape tag; amended 2026-09-13 under P8: the tag is no longer purely a shape claim). Both are read off tags classify already recorded rather than off a predicate of M4's own, and both witnesses are real corpus names rather than constructed cases, so each carve-out has something in the differential that would notice its loss. Mutation-checked on a scratch copy: dropping the `initial` carve-out fails that name's case row, its facade twin, M4's own boundary example and the pre-existing assertion in test_the_chain_and_the_walk_stop_where_the_peel_begins; dropping `vocab:bound-given` fails the other name's two runners, M4's boundary, P5's own doc example, O5's own `abd née Jones` line and the corpus-wide maiden-clause property on 'abdul' -- six in all, the O5 line having been added by the review round, and the list is exhaustive as re-run against the final tree. +- 2026-08-27 #445 (its "a word the vocabulary claims as a given name", which meant the bound-given claim, superseded in words by 2026-11-05 #815) — the two carve-outs are not inventions, and both rest on mechanisms.md#TWO-LAYER-ASSIGN: the positional layer never overrides a vocabulary claim, and M4 changes only what POSITION decided. A word the vocabulary claims as a given name keeps that reading ('abd née Jones' — `vocab:bound-given`), and so does a word written as an initial ('J. née Jones Smith V' — the `initial` shape tag; amended 2026-09-13 under P8: the tag is no longer purely a shape claim). Both are read off tags classify already recorded rather than off a predicate of M4's own, and both witnesses are real corpus names rather than constructed cases, so each carve-out has something in the differential that would notice its loss. Mutation-checked on a scratch copy: dropping the `initial` carve-out fails that name's case row, its facade twin, M4's own boundary example and the pre-existing assertion in test_the_chain_and_the_walk_stop_where_the_peel_begins; dropping `vocab:bound-given` fails the other name's two runners, M4's boundary, P5's own doc example, O5's own `abd née Jones` line and the corpus-wide maiden-clause property on 'abdul' -- six in all, the O5 line having been added by the review round, and the list is exhaustive as re-run against the final tree. - 2026-08-27 #445 — the two halves of Derek's answer differ in their relationship to 1.4.0, and a reader should not have to re-derive it. The bracketed spelling RESTORES v1: `Smith (née Jones)` read family 'Smith', nickname 'née Jones' on 1.4.0, 2.0.0 and 2.1.0 alike, and now reads family 'Smith', maiden 'Jones' — the clause changes hands and the family name stays put, so the 1.4.0 gate's diff on that name SHRANK to {nickname, maiden}. The interior spelling is a NEW reading: `Jane née Jones Smith` read first 'Jane', middle 'née Jones', last 'Smith' on 1.4.0 and reads family 'Jane', maiden 'Jones Smith' now, the real surname being inside the maiden value by M2's greedy take. That the marker stands inside the name changes nothing for M4, which counts what the take LEAVES rather than where the marker stood — one name word left that way is one name word, which is the widest half of the decision and the half no earlier version agrees with. - 2026-08-27 #445 (its `'Smitty' Jones Jr. née Smith` witness superseded in part by #601, decisions/M2, a marker behind a credential being an ordinary word; its reason N3 declines, a count not setting a suffix aside, superseded by #815, decisions/N3, N3 now leaving a name with a maiden name to M4) — a precedence claim corrected while drafting, and it is exactly the class this bundle keeps producing. The first draft of M4 said a name carrying a nickname is N3's rather than this rule's. Measured false: `'Smitty' Jones Jr. née Smith` reads family 'Jones', because N3's count does not set a suffix aside, so N3 declines and M4 fires. A nickname holds nothing off — where N3 has already named the family M4 finds nothing left to move, and where N3 declined M4 names it. The general lesson is the one #410 and #411 already taught from the other side: a rule that counts name words and a rule that counts something else will disagree at the edges, and the disagreement is only visible if the interaction is measured rather than asserted. - 2026-08-27 #445 — what the ledger's `# revisit when #445 lands` markers bought, and what they got wrong. Four blocks carried them, and each predicted that a "keep the family" fix would leave the diff a subset of the fields its rule already declared, so the rule would go on explaining the name and the change would be absorbed with the gate green. That was wrong in a way the rule's own shape settles: M4 MOVES the one name word rather than adding one, so `given` empties as `family` fills, the diff outgrows every declaration, and eight names arrived UNEXPLAINED at all three baselines. Two counts run through this and they are different sets, so name which is which: NINE corpus names change reading, of which eight arrive as new diffs — the ninth, 'Smith (née Jones)', has its 1.4.0 diff SHRINK instead, its family agreeing with v1 again. The four markers between them named NINE names to re-measure, of which seven moved: the two that did not are M4's carve-outs, and the two movers the markers could not name were not corpus names until this change's own examples added them. The markers earned their keep all the same — they named the right rule, the right field and very nearly the right set — so they are corrected in place rather than deleted, and the correction says what actually happened. THREE of the four moved in the opposite direction from their own prediction, and getting that number right took two passes. The fix(#335) rule for 'Smith (née Jones)' appears in all three ledgers, and every copy feared absorbing a WIDENED diff while the diff in fact SHRANK to {nickname, maiden}. The first pass narrowed only the 1.4.0 copy, on a measurement of that wheel, and left the other two at four fields on the reasoning that 2.0.0 and 2.1.0 'read `given`, and the baseline cannot move'. They did not: only the BARE spelling ever read `given`, and this rule holds the bracketed one, which reads family 'Smith', nickname 'née Jones' on every released version. So two rules stood over a two-field diff declaring four, and classify's subset test would have explained a `given`/`family` regression on that name in silence -- the absorption those very notes existed to prevent, surviving the round that answered them. A third reviewer found it by instrumenting the comparator to dump real diff-field sets, and that is the lesson worth keeping: ledger prose cannot be checked by reading it, and the round that corrects a marker is exactly where a wrong premise gets written down with confidence. @@ -30,4 +31,4 @@ Open: none in this file. - 2026-08-27 #445 (review round) — M4 is keyed on the maiden NAME, not on a marker, and the statement was corrected to say so after two reviewers measured the same defect independently. The guard tests for a token in the MAIDEN role, and M1's caller-configured pair produces one with no marker anywhere: under `Policy(maiden_delimiters=frozenset({("(", ")")}))`, `Smith (Jones)` reads family 'Smith', maiden 'Jones', and so do M1's own boundary examples `Smith (Nee)` and `Smith (z domu)`. The BEHAVIOUR is right — the rationale transfers to a declared pair without a word of change, since what announces a former surname is the clause, not the vocabulary that marked it — so the fix was to the rule, which had said "a recognized maiden marker that takes its name and leaves exactly one name word" and now says "a maiden name standing beside exactly one name word". That covers M1, M2 and M3 uniformly, M1 is in M4's `interacts:` and M4 in M1's, and the configured path has an example line of its own. The general lesson is the one this bundle keeps teaching from a new angle: a statement written from the case that prompted the change describes that case, not the code, and only measuring the OTHER paths into the same guard finds the difference. - 2026-08-27 #445 (review round) — a known gap recorded rather than closed, the way H1 carries its own. M4's guard counts GIVEN tokens; H1 counts nothing at all (it tests which roles are unoccupied). So a name word another rule has joined counts as several here and M4 declines where H1 fires: `Dr. Dean of Chemistry` reads family 'Dean of Chemistry' while `Dean of Chemistry née Jones` keeps given 'Dean of Chemistry', the connective join (P3) having left three GIVEN tokens. rules/P3 says the joined part is one name word wherever another rule counts them, so the two siblings genuinely disagree and this is a gap rather than a boundary. Not closed here: widening the count to units moves zero corpus names (measured), and a behaviour change nobody has approved does not belong in a branch whose blast radius was settled. The sibling claim in the code comment and in this entry is narrowed to match — sibling except in what it counts. - 2026-08-27 #445 — the relationship to #449, briefly, because the two look like the same question and are not. #449 asks whether a lone name word with nothing to decide it should REPORT an ambiguity; #445 removes a class of names from that population by giving them something that decides. So #445 reduces #449's reach rather than competing with it, and #449's measurement — a naive "one name word, nothing decided it" condition fires on 19 of 1,085 corpus names, only three or four of them the case it is about — is re-taken after this lands. O5 cites #449 in prose and deliberately carries no `deviates:` marker: that marker asserts an intended output the runner then checks strictly, and #449 had not decided one. It has since — 2026-09-07, decisions/O5 — and the answer arrived as ordinary example lines rather than as a marker, the report being shipped behavior and not a deviation. The re-measurement this bullet promises is taken there: the naive condition is wider than either number suggests, firing on 143 of the 1123 corpus names, and O5's own population is 27. - +- 2026-11-05 #815 — THE BOUND-GIVEN CARVE-OUT SAYS WHAT IT READS, AND THE FLIP OF EVERY OTHER GIVEN READING IS A STATED COST (decided). The Except said "a word the vocabulary has claimed as a given name keeps that reading", while the guard has always read only the `vocab:bound-given` tag (`_NEVER_FLIPPED`, with `initial`). Other given-name readings were flipped from the start: at #445's own commit (976cd333) the ambiguous particles, `particles_ambiguous`, read family beside a maiden name (`Van née Jones`, `Di née Jones`), and the `given` readings the per-word vocabulary added later on particles, titles and credentials (from 2026-10-19: #765, #769, #773, #794, #796, #806, #858, #876, and #883 on 2026-10-25, which turned phase 1's `may_be_given` flag into the `given` readings the ambiguous particles carry, `van` among them), on titles that are also given names (#752's phase 2i) and on given names written short (#789) read family too (`Chas. née Jones`, `Dean née Jones` → family at master 5c3c0db0, under every order). Two ways were weighed. Widening the carve-out to the given names written short, which mechanisms.md#TWO-LAYER-ASSIGN's "never overrides a vocabulary claim" could be read to ask, was declined: measured by adding `vocab:given-abbreviation` to `_NEVER_FLIPPED` over every `tools/differential/corpus*.jsonl` name under the three orders, it moves one name, this entry's own `Chas. née Jones`, so the corpora decide nothing and the ground is the rule's. Kept instead: a bound given name and an initial claim what a word IS, while a plain `given` reading says only that it may be a given name, and the maiden marker answers that, naming the word beside it as the surname the bearer carries now. H1 reads such a word as the family name too (`Dr. Chas.`, `Dr. Dean`), though not by this line, flipping an initial as well (`Dr. J.` → family 'J.'), so the line M4 draws rests on its Except's own reason; mechanisms.md#TWO-LAYER-ASSIGN now says that a `given` reading is no claim in its sense. The words were narrowed to the code, the cost moved into a new Accepted bullet with `Chas. née Jones` and `Van née Jones` as its examples, and the Except's "which is nobody's family name" went, being false under both family-first orders, where an initial reads family by position (`J. née Jones Smith V` → family 'J.'). Nothing in the parser moved. Found by the third review round of #815 (PR #1107), whose O5 edit had copied the wider words. diff --git a/docs/design/mechanisms.md b/docs/design/mechanisms.md index 5fb4d6b02..8ac6ce695 100644 --- a/docs/design/mechanisms.md +++ b/docs/design/mechanisms.md @@ -98,7 +98,7 @@ This catalog converts discovery into a one-time cost — it does not remove disc **Contract statement.** A vocabulary layer first claims words for what they ARE, wherever they sit; a positional layer then reads every unclaimed word by where it STANDS. Every rule belongs to exactly one layer — with one named exception: the leading-abbreviation shape (rule H2) fires before the suffix vocabulary is consulted, so "Esq. Smith" reads title, not suffix. -**How it works.** The two layers compose without ordering bugs because the positional layer never overrides a vocabulary claim (rule O4 is the positional layer's contract). The exception is still ONE, re-checked 2026-09-08 against the trailing title run (rule H5), which reads title vocabulary in the trailing slot and is NOT a second one: it runs after the suffix peel rather than before it, so a post-nominal keeps its claim — `John Smith Esq.` reads suffix and `John Smith Prof. Jr.` reads suffix `Jr.`, both measured. That rule is also the worked answer to the Reach-for-it line below: it wanted a word's identity and its position at once and was split by SLOT, the front asking about shape (H2) and the back about vocabulary (H5), two questions with two criteria rather than one rule fighting both layers. +**How it works.** The two layers compose without ordering bugs because the positional layer never overrides a vocabulary claim (rule O4 is the positional layer's contract). The exception is still ONE, re-checked 2026-09-08 against the trailing title run (rule H5), which reads title vocabulary in the trailing slot and is NOT a second one: it runs after the suffix peel rather than before it, so a post-nominal keeps its claim — `John Smith Esq.` reads suffix and `John Smith Prof. Jr.` reads suffix `Jr.`, both measured. That rule is also the worked answer to the Reach-for-it line below: it wanted a word's identity and its position at once and was split by SLOT, the front asking about shape (H2) and the back about vocabulary (H5), two questions with two criteria rather than one rule fighting both layers. A claim here is a word's role, not every reading the vocabulary records: a `given` reading says only that a word may be a given name, and the rules that decide a lone word's field read past it, H1 and M4 both reading such a word as the family name (`Dr. Chas.`, `Chas. née Jones`), M4 keeping only a bound given name and an initial (decisions/M4's 2026-11-05 #815 entry). **Lives in.** _classify/_group (vocabulary side), _assign (positional side). diff --git a/docs/design/rules/M4-maiden-marker-makes-the-lone-name-word-the-family.md b/docs/design/rules/M4-maiden-marker-makes-the-lone-name-word-the-family.md index 4b0752879..32a25bbf0 100644 --- a/docs/design/rules/M4-maiden-marker-makes-the-lone-name-word-the-family.md +++ b/docs/design/rules/M4-maiden-marker-makes-the-lone-name-word-the-family.md @@ -24,7 +24,7 @@ **Except:** -- **A word the vocabulary has claimed as a given name keeps that reading, and so does a word read as an initial** (T4, T5), which is nobody's family name. Both are beyond the rule's reach for one reason: it changes what POSITION would have decided, so it cannot overrule what a word already IS (mechanisms.md#TWO-LAYER-ASSIGN). +- **A bound given name keeps the reading its position gives it, and so does a word read as an initial** (P5, T4, T5). Both are beyond the rule's reach for one reason: it changes what POSITION would have decided, so it cannot overrule what a word already IS (mechanisms.md#TWO-LAYER-ASSIGN). ``` "abd née Jones" → given="abd" · boundary "J. née Jones Smith V" → given="J." · boundary @@ -35,6 +35,14 @@ - **A name carrying a TITLE** is H1's rather than this rule's, H1's given-name-title carve-out included, which keeps the word a given name. +**Accepted:** + +- A word the vocabulary reads as possibly a given name, without the claim a bound given name makes, is the family name all the same — a given name written short, a title or a particle that may also be a given name — since the marker names the word beside it as the surname the bearer carries now. + ``` + "Chas. née Jones" → family="Chas." + "Van née Jones" → family="Van" + ``` + --- **Signal:** count **history:** decisions/M4 · **implemented:** nameparser/_pipeline/_post_rules.py diff --git a/nameparser/_pipeline/_assign.py b/nameparser/_pipeline/_assign.py index 72cc56a21..dc9ef008d 100644 --- a/nameparser/_pipeline/_assign.py +++ b/nameparser/_pipeline/_assign.py @@ -212,8 +212,8 @@ def _absorbed(piece: Sequence[int], tokens: Sequence[WorkToken], #: could speak, so O5's convention decided nothing. Built from M4's #: `_NEVER_FLIPPED` pair rather than respelling it: the two sets answer #: different questions -- may M4 retag the word, and did anything -#: decide the field -- and share the pair because a word vocabulary -#: claimed as a given name, or wrote as an initial, answers both. The +#: decide the field -- and share the pair because a bound given name, +#: or a word written as an initial, answers both. The #: third, `particle`, is here alone because a lone particle's reading #: is P4's. None is a predicate this emitter owns: they are read off #: the tags classify already recorded (mechanisms.md#TWO-LAYER-ASSIGN). diff --git a/nameparser/_pipeline/_post_rules.py b/nameparser/_pipeline/_post_rules.py index b64feebb1..dd4ee656c 100644 --- a/nameparser/_pipeline/_post_rules.py +++ b/nameparser/_pipeline/_post_rules.py @@ -894,8 +894,8 @@ def post_rules(state: ParseState) -> ParseState: # another rule counts them, so the two disagree; widening moves # no corpus name and is not this change's to make # (decisions/M4). - # rules/M4: "a word the vocabulary has claimed as a given name - # keeps that reading, and so does a word read as an initial" + # rules/M4: "a bound given name keeps the reading its position + # gives it, and so does a word read as an initial" # -- read off the tags classify already recorded rather than a # predicate of this rule's own, because this rule changes what # POSITION decided and must not reach what a word IS diff --git a/tests/v2/rules_budget.json b/tests/v2/rules_budget.json index 268c89d3e..70243d622 100644 --- a/tests/v2/rules_budget.json +++ b/tests/v2/rules_budget.json @@ -30,7 +30,7 @@ "M1": {"words": 239, "then_words": 119, "because_sentences": 2, "except": 1, "precedence": 2, "accepted": 0, "accepted_words": 0}, "M2": {"words": 755, "then_words": 435, "because_sentences": 1, "except": 4, "precedence": 1, "accepted": 6, "accepted_words": 204}, "M3": {"words": 239, "then_words": 84, "because_sentences": 2, "except": 2, "precedence": 2, "accepted": 1, "accepted_words": 93}, - "M4": {"words": 331, "then_words": 168, "because_sentences": 2, "except": 1, "precedence": 1, "accepted": 0, "accepted_words": 0}, + "M4": {"words": 325, "then_words": 168, "because_sentences": 2, "except": 1, "precedence": 1, "accepted": 1, "accepted_words": 59}, "N1": {"words": 95, "then_words": 62, "because_sentences": 1, "except": 0, "precedence": 0, "accepted": 0, "accepted_words": 0}, "N2": {"words": 131, "then_words": 79, "because_sentences": 1, "except": 0, "precedence": 0, "accepted": 0, "accepted_words": 0}, "N3": {"words": 156, "then_words": 34, "because_sentences": 1, "except": 1, "precedence": 1, "accepted": 5, "accepted_words": 249}, diff --git a/tools/differential/corpus_rules.jsonl b/tools/differential/corpus_rules.jsonl index 0c90dfaac..a8af418fb 100644 --- a/tools/differential/corpus_rules.jsonl +++ b/tools/differential/corpus_rules.jsonl @@ -157,6 +157,7 @@ "Chancellor Smith" "Chas. Smith" "Chas. Smith, Ed" +"Chas. née Jones" "Cheikh Anta Diop" "Chief Dean and Mary Smith" "Chief Justice John Roberts" @@ -1264,6 +1265,7 @@ "Van Gogh Vincent" "Van Johnson" "Van der Merwe Jan" +"Van née Jones" "Vega, Juan de la" "Vincent van Gogh van Beethoven" "W. Russell (Jr.) Withers" diff --git a/tools/differential/snapshot.jsonl b/tools/differential/snapshot.jsonl index 98d87849a..facd77752 100644 --- a/tools/differential/snapshot.jsonl +++ b/tools/differential/snapshot.jsonl @@ -592,6 +592,7 @@ {"name": "Charles van der van der Berg", "given": "Charles", "family": "van der van der Berg", "initials": "C. B."} {"name": "Chas. Smith", "given": "Chas.", "family": "Smith", "initials": "C. S."} {"name": "Chas. Smith, Ed", "given": "Chas.", "family": "Smith", "suffix": "Ed", "ambiguities": ["SUFFIX_OR_NAME"], "alternatives": ["SUFFIX_OR_NAME: name as given (declared)"], "initials": "C. S.", "capitalized_force": "Chas. Smith, ED"} +{"name": "Chas. née Jones", "family": "Chas.", "maiden": "Jones", "initials": "C."} {"name": "Chattel, Frederik Jacobus van Rossum", "given": "Frederik", "middle": "Jacobus van Rossum", "family": "Chattel", "initials": "F. J. R. C."} {"name": "Cheikh Anta Diop", "given": "Cheikh", "middle": "Anta", "family": "Diop", "initials": "C. A. D."} {"name": "Chemistry Jane Smith", "given": "Chemistry", "middle": "Jane", "family": "Smith", "initials": "C. J. S."} @@ -3934,6 +3935,7 @@ {"name": "Van der Merwe Jan Koos", "order": "FAMILY_FIRST", "given": "der Merwe Jan Koos", "family": "Van", "ambiguities": ["PARTICLE_OR_GIVEN"], "alternatives": ["PARTICLE_OR_GIVEN: particle as family (vocabulary)"], "initials": "d. M. J. K. V.", "capitalized_force": "Van Der Merwe Jan Koos"} {"name": "Van der Merwe, Jan Koos", "given": "Jan", "middle": "Koos", "family": "Van der Merwe", "initials": "J. K. M.", "capitalized_force": "Jan Koos van der Merwe"} {"name": "Van der Walt", "given": "Van", "family": "der Walt", "ambiguities": ["PARTICLE_OR_GIVEN"], "alternatives": ["PARTICLE_OR_GIVEN: particle as family (vocabulary)"], "initials": "V. W."} +{"name": "Van née Jones", "family": "Van", "maiden": "Jones", "initials": "V."} {"name": "Varano, Costanza da", "given": "Costanza", "family": "da Varano", "ambiguities": ["PARTICLE_OR_GIVEN"], "alternatives": ["PARTICLE_OR_GIVEN: name as middle (declared)"], "initials": "C. V."} {"name": "Vatson Con Hamiş", "order": "FAMILY_FIRST", "given": "Con", "middle": "Hamiş", "family": "Vatson", "initials": "C. H. V."} {"name": "Vega Smith", "given": "Vega", "family": "Smith", "initials": "V. S."}