From a7d8583c0f5267fbda9165acac3a7fef786cf045 Mon Sep 17 00:00:00 2001 From: Derek Gulbranson Date: Fri, 16 Oct 2026 19:22:38 -0700 Subject: [PATCH 1/2] Add a conventions corpus: invented names for traditions the corpora miss Our corpora cover Western and CJK names well and have almost none from traditions with no family name, religious names, positional patronymics or honorifics written after the name (#686). conventions.py is a hand-written table of 35 invented names patterned on documented conventions, each with its tradition, the convention it exercises, and the reading a reader would expect; build_conventions_corpus.py writes corpus_conventions.jsonl from it, a non-default order as its shapes.py id, and test_corpora.py pins the file to the table. The expectation is a note, not a pin. Derek chose no fields file: many expectations need fields the model lacks (a patronymic, no family name), and the agreement scorer reads an unstated part as an empty role. The snapshot gains 35 names, none moved; all 35 readings match the ones the issue measured on 1a4e8a10. The snapshot check reads 4,941 entries in about 2s, so the issue's runtime question is moot. Co-Authored-By: Claude Opus 5.5 --- tests/v2/test_corpora.py | 9 + tools/differential/README.md | 24 ++- .../differential/build_conventions_corpus.py | 65 ++++++++ tools/differential/conventions.py | 154 ++++++++++++++++++ tools/differential/corpus_conventions.jsonl | 35 ++++ tools/differential/snapshot.jsonl | 35 ++++ 6 files changed, 319 insertions(+), 3 deletions(-) create mode 100644 tools/differential/build_conventions_corpus.py create mode 100644 tools/differential/conventions.py create mode 100644 tools/differential/corpus_conventions.jsonl diff --git a/tests/v2/test_corpora.py b/tests/v2/test_corpora.py index fce0a5e0..b4472ae0 100644 --- a/tests/v2/test_corpora.py +++ b/tests/v2/test_corpora.py @@ -42,6 +42,15 @@ def test_shapes_corpus_matches_the_case_table() -> None: "`uv run python tools/differential/build_shapes_corpus.py`") +def test_conventions_corpus_matches_its_table() -> None: + """corpus_conventions.jsonl is generated from conventions.py's + hand-written table (#686).""" + module = load_tool("build_conventions_corpus") + assert _checked_in("corpus_conventions.jsonl") == module.selected(), ( + "corpus_conventions.jsonl is stale: regenerate with " + "`uv run python tools/differential/build_conventions_corpus.py`") + + def test_case_shape_ids_exist_in_the_inventory() -> None: """cases.py cannot import tools/, so Case.__post_init__ validates every shape tag against its own hand copy of the inventory's ids diff --git a/tools/differential/README.md b/tools/differential/README.md index d87c3015..bbc4c8fe 100644 --- a/tools/differential/README.md +++ b/tools/differential/README.md @@ -189,6 +189,7 @@ invocation shows it. | `corpus_cldr.jsonl` | Unicode CLDR's person-name formatting test data at `release-48`: each fictional name's long, formal rendering in givenFirst, surnameFirst and sorting order, about 110 locales in native scripts, via `build_cldr_corpus.py` (2026-10-12); Unicode-3.0, notice in `cldr_LICENSE` | real-world name distributions: the names are written to fill every field, so full-house names are over-represented and plain two-word names under-represented | | `corpus_gnd.jsonl` | the German National Library's authority file (GND, via lobid), real people who are deceased and have a Wikipedia article: each preferred name as cataloged (`Gogh, Vincent van`) and, outside family-first areas, a given-first rendering composed from its fields (a regnal name is composed only, `Johann II.`, without its German descriptor), sampled by shape and area via `build_gnd_corpus.py` (2026-10-16); CC0, credit in `gnd_LICENSE` | names as their bearers write them: German library romanization and German forms for historic figures, Latin script only, titles, credentials and nicknames kept out of the preferred name (a few slip into a `personalName`: `Imam Bonjol`), and the catalog's entry rules (not the bearer's culture) decide what counts as a surname | | `corpus_wikidata.jsonl` | Wikidata, real public figures (deceased, or with at least 10 sitelinks) whose item states a second surname (P1950: Spain, Mexico, Colombia) or a patronymic (P5056: Russia, the Soviet Union, the Russian Empire, Iceland, Malaysia): each P1559 native-language name and own-language label whose every word aligns with exactly one stated part, via `build_wikidata_corpus.py` (2026-10-16); CC0, credit in `wikidata_LICENSE` | everything the strict alignment drops: short display forms without the second surname, nicknames, and names with an unrecorded part, so tidy names are over-represented; only those eight citizenships; no titles, credentials or suffixes | +| `corpus_conventions.jsonl` | invented names patterned on naming conventions the other corpora barely cover -- no family name, religious names, positional patronymics, honorifics after the name -- from the hand-written table in `conventions.py`, via `build_conventions_corpus.py` (#686) | real names, and every convention nobody has written a row for: about one row per convention, so it shows that a convention moved, not how often | | `corpus_rules.jsonl` | every example in `docs/design/rules.md`, via `build_rules_corpus.py` (#414) | anything the rules doc has no example for | | `corpus_shapes.jsonl` | shape-tagged rows of `tests/v2/cases.py`, via `build_shapes_corpus.py` (#468) | anything no one has tagged a row for | @@ -301,12 +302,29 @@ uv run python tools/differential/build_cjk_corpus.py ``` Every distinct CJK-bearing `text` in `tests/v2/cases.py`, `tolerated` -rows included. The generated corpora (`corpus_cjk`, `corpus_rules`, -`corpus_shapes`) are each pinned by `tests/v2/test_corpora.py` against -their generator's selection, so a case row or rules.md example added +rows included. The generated corpora (`corpus_cjk`, `corpus_conventions`, +`corpus_rules`, `corpus_shapes`) are each pinned by `tests/v2/test_corpora.py` against +their generator's selection, so a case row, a rules.md example or a +`conventions.py` row added without regenerating fails the suite instead of silently narrowing what the snapshot watches. +`corpus_conventions.jsonl` is generated from `conventions.py`, a table +whose rows record the tradition, the convention a name exercises, and +what a reader who knows the convention would take each part to be: + +``` +uv run python tools/differential/build_conventions_corpus.py +``` + +That expectation is a note, not a pin, and nothing scores against +it: many are stated in terms the model cannot express yet (a +patronymic, a name with no family name), and a fields file would +read each such unstated part as an empty role (#686). A row whose +reading is settled graduates to `tests/v2/cases.py`. The names are +invented, never copied from the references the conventions come +from. + ## What the corpora do not cover The corpora run under the **default policy**, so any behavior gated diff --git a/tools/differential/build_conventions_corpus.py b/tools/differential/build_conventions_corpus.py new file mode 100644 index 00000000..0ec1dec1 --- /dev/null +++ b/tools/differential/build_conventions_corpus.py @@ -0,0 +1,65 @@ +"""Regenerate corpus_conventions.jsonl from conventions.py's table (#686). + +The table holds invented names patterned on naming conventions the other +corpora barely cover; conventions.py says where the conventions come +from and why each row's expected reading is a note rather than a pin. +A row read under a non-default order is written with the shapes.py id +for that order, so the snapshot reads it under that order. + +Regenerate after editing the table: + + uv run python tools/differential/build_conventions_corpus.py + +tests/v2/test_corpora.py pins the checked-in file against this module's +selection, so a row added without regenerating fails the suite. +""" +from __future__ import annotations + +import json +import sys +from pathlib import Path + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE)) + +from conventions import CONVENTIONS # noqa: E402 +from shapes import SHAPES # noqa: E402 + +OUT = HERE / "corpus_conventions.jsonl" + + +def _shape_for(order: str) -> int: + """The one shapes.py id that is an input shape for `order`.""" + ids = [k for k, shape in SHAPES.items() if shape.order == order] + if len(ids) != 1: + raise ValueError(f"conventions.py names order {order!r}, which " + f"{len(ids)} shapes.py shapes declare; use one of " + f"{sorted({s.order for s in SHAPES.values() if s.order})}") + return ids[0] + + +def selected() -> list[object]: + """The corpus lines, in table order: a bare name under the default + order, else the name with its order's shape.""" + seen: set[tuple[str, str | None]] = set() + lines: list[object] = [] + for row in CONVENTIONS: + if (row.name, row.order) in seen: + raise ValueError(f"conventions.py lists {row.name!r} under " + f"{row.order or 'the default order'} twice") + seen.add((row.name, row.order)) + lines.append(row.name if row.order is None + else {"name": row.name, "shape": _shape_for(row.order)}) + return lines + + +def main() -> None: + lines = selected() + with OUT.open("w", encoding="utf-8") as fh: + for line in lines: + fh.write(json.dumps(line, ensure_ascii=False) + "\n") + print(f"wrote {len(lines)} names to {OUT.name}") + + +if __name__ == "__main__": + main() diff --git a/tools/differential/conventions.py b/tools/differential/conventions.py new file mode 100644 index 00000000..a70b62a7 --- /dev/null +++ b/tools/differential/conventions.py @@ -0,0 +1,154 @@ +"""Hand-written names for naming conventions the other corpora barely +cover (#686): traditions with no family name, religious names, +patronymics placed by position, honorifics written after the name. + +Every name here is INVENTED, patterned on a convention documented in +naming-practice references (a 2006 UK government guide distributed by +Interpol among them, which carries no licence notice), never copied from +one. build_conventions_corpus.py writes corpus_conventions.jsonl from +this table, and the snapshot watches those names like every other +corpus's. + +`expect` is a NOTE, not a pin: what a reader who knows the convention +would take each part to be, often in terms the model cannot express yet +(a patronymic, a name with no family name, an honorific that is not a +title). Nothing scores the parser against it (#686 decided against a +fields file). Today's reading is deliberately not recorded here either: +snapshot.jsonl holds it, and a second copy would go stale. A row whose +reading is settled can graduate to tests/v2/cases.py, where it becomes a +contract. + +`order` is a public nameparser constant name, as in shapes.py; None is +the default order. +""" +from typing import NamedTuple + + +class Convention(NamedTuple): + tradition: str + convention: str + name: str + order: str | None + expect: str + + +CONVENTIONS: tuple[Convention, ...] = ( + Convention("Somali", "given + father's + grandfather's name, no family name", + "Hodan Farah Warsame", None, + "given Hodan; Farah and Warsame are her father's and grandfather's " + "given names, not a family name"), + Convention("Sikh", "religious name between given and family name", + "Harpreet Kaur Dhillon", None, + "given Harpreet; Kaur is the religious name every Sikh woman bears, " + "written as a surname when no family name is; family Dhillon"), + Convention("Tamil", "father's given name as a leading initial", + "K. Sivakumar", None, + "K. is the father's given name; Sivakumar is the person's own given " + "name; no family name"), + Convention("Spanish", "H. (hijo) as the Jr. equivalent", + "Pedro López Ruiz H.", None, + "given Pedro; family López Ruiz (paternal and maternal surnames); " + "H. a generational suffix"), + Convention("Spanish", "Vda. de (widow of) before the late husband's surname", + "Carmen Díaz Vda. de Mora", None, + "given Carmen; her own family name Díaz; Vda. de Mora marks her as " + "the widow of a Mora"), + Convention("Turkish", "oğlu ('son of') written apart, part of the family name", + "Ali Kara Oğlu", None, + "given Ali; family Kara Oğlu, the separated spelling of Karaoğlu"), + Convention("Turkish", "honorific after the given name", + "Murat Bey", None, + "given Murat; Bey an honorific, not a family name"), + Convention("Hungarian", "title after the name", + "Szabó Péter úr", "FAMILY_FIRST", + "family Szabó, given Péter; úr ('Mr.') a title written last"), + Convention("Hungarian", "married form: -né on the husband's given name", + "Szabó Péterné", "FAMILY_FIRST", + "family Szabó; Péterné ('wife of Péter') stands where her given " + "name would"), + Convention("Korean", "two-syllable given name written as two words", + "Kim Min Ho", "FAMILY_FIRST", + "family Kim; given Min Ho, one name in two words"), + Convention("Vietnamese", "Thi as the female middle name", + "Tran Thi Mai", "FAMILY_FIRST", + "family Tran; middle Thi; given Mai, which the convention writes " + "last (the order FAMILY_FIRST_GIVEN_LAST names)"), + Convention("Bulgarian", "patronymic between given and family name", + "Ivan Petrov Dimitrov", None, + "given Ivan; Petrov his patronymic, from his father Petar; family " + "Dimitrov"), + Convention("Filipino", "Ma. for María, maternal surname in the middle", + "Ma. Teresa Cruz Bautista", None, + "given Ma. Teresa (Ma. is María, not a title); Cruz the mother's " + "surname; family Bautista"), + Convention("Korean", "romanized honorific, spaced", + "Park Ji-hoon ssi", "FAMILY_FIRST", + "family Park; given Ji-hoon; ssi (씨) an honorific"), + Convention("Japanese", "romanized honorific, spaced", + "Suzuki san", "FAMILY_FIRST", + "family Suzuki; san an honorific; no given name"), + Convention("Japanese", "romanized honorific, hyphenated", + "Suzuki-san", "FAMILY_FIRST", + "family Suzuki; -san an honorific glued to it"), + Convention("Burmese", "no family name; honorific U for a man", + "U Kyaw Win", None, + "U an honorific; Kyaw Win the whole personal name; no family name"), + Convention("Burmese", "honorific Daw for a woman", + "Daw Thida", None, + "Daw an honorific; Thida the whole personal name"), + Convention("Thai", "Khun before the given name", + "Khun Malee", None, + "Khun a polite title; Malee the given name, which Thai address uses"), + Convention("Malay", "bin ('son of') patronymic, no family name", + "Hassan bin Yusof", None, + "given Hassan; bin Yusof his patronymic; no family name"), + Convention("Malay", "bin abbreviated B.", + "Hassan B. Yusof", None, + "as Hassan bin Yusof: B. is bin, not a middle initial"), + Convention("Malaysian Indian", "a/l (anak lelaki, 'son of')", + "Suresh a/l Muthu", None, + "given Suresh; a/l Muthu his patronymic; no family name"), + Convention("Malaysian Indian", "a/p (anak perempuan, 'daughter of')", + "Kavitha a/p Raman", None, + "given Kavitha; a/p Raman her patronymic; no family name"), + Convention("Indonesian", "H. (Haji), a title shaped like an initial", + "H. Budi Santoso", None, + "H. a title (one who has made the hajj); given Budi; Santoso a " + "second given name or a family name"), + Convention("Kalenjin", "arap ('son of')", + "David arap Kirui", None, + "given David; arap Kirui, used as a family name"), + Convention("Maasai", "ole ('son of')", + "Joseph ole Sankale", None, + "given Joseph; ole Sankale, used as a family name"), + Convention("Kikuyu", "wa ('of')", + "Wanjiru wa Kamau", None, + "given Wanjiru; wa Kamau names her father"), + Convention("Hong Kong", "English given name before the Chinese name", + "Michael Wong Kar Ming", None, + "given Michael; family Wong; Kar Ming the Chinese given name"), + Convention("Singapore", "English given name after the Chinese name", + "Lim Mei Ling Jessica", "FAMILY_FIRST", + "family Lim; Mei Ling the Chinese given name; Jessica the English " + "given name"), + Convention("Cantonese", "given name that is also a title modifier", + "Wing Lau", None, + "given Wing, not a title; family Lau"), + Convention("Hungarian", "married form on the husband's family name", + "Szabóné Kiss Éva", "FAMILY_FIRST", + "Szabóné ('wife of Szabó') a married form; family Kiss; given Éva"), + Convention("Afrikaans/Dutch", "capitalized particle, no given name", + "Van der Walt", None, + "family Van der Walt; no given name"), + Convention("Arabic", "kunya ('father of')", + "Abu Karim", None, + "a kunya, 'father of Karim', used as a name of address; not a given " + "name plus a family name"), + Convention("Iranian", "-zadeh written as a separate word", + "Reza Hossein Zadeh", None, + "given Reza; family Hossein Zadeh, the separated spelling of " + "Hosseinzadeh"), + Convention("French", "index form, elided particle after the given name", + "Orval, Pierre d'", None, + "family d'Orval; given Pierre; d' belongs to the family"), +) diff --git a/tools/differential/corpus_conventions.jsonl b/tools/differential/corpus_conventions.jsonl new file mode 100644 index 00000000..d7a70be8 --- /dev/null +++ b/tools/differential/corpus_conventions.jsonl @@ -0,0 +1,35 @@ +"Hodan Farah Warsame" +"Harpreet Kaur Dhillon" +"K. Sivakumar" +"Pedro López Ruiz H." +"Carmen Díaz Vda. de Mora" +"Ali Kara Oğlu" +"Murat Bey" +{"name": "Szabó Péter úr", "shape": 4} +{"name": "Szabó Péterné", "shape": 4} +{"name": "Kim Min Ho", "shape": 4} +{"name": "Tran Thi Mai", "shape": 4} +"Ivan Petrov Dimitrov" +"Ma. Teresa Cruz Bautista" +{"name": "Park Ji-hoon ssi", "shape": 4} +{"name": "Suzuki san", "shape": 4} +{"name": "Suzuki-san", "shape": 4} +"U Kyaw Win" +"Daw Thida" +"Khun Malee" +"Hassan bin Yusof" +"Hassan B. Yusof" +"Suresh a/l Muthu" +"Kavitha a/p Raman" +"H. Budi Santoso" +"David arap Kirui" +"Joseph ole Sankale" +"Wanjiru wa Kamau" +"Michael Wong Kar Ming" +{"name": "Lim Mei Ling Jessica", "shape": 4} +"Wing Lau" +{"name": "Szabóné Kiss Éva", "shape": 4} +"Van der Walt" +"Abu Karim" +"Reza Hossein Zadeh" +"Orval, Pierre d'" diff --git a/tools/differential/snapshot.jsonl b/tools/differential/snapshot.jsonl index fcf7042e..f22f5e3c 100644 --- a/tools/differential/snapshot.jsonl +++ b/tools/differential/snapshot.jsonl @@ -35,6 +35,7 @@ {"name": "Abu Bakar", "given": "Abu", "family": "Bakar", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "A. B."} {"name": "Abu Bakar Salim", "given": "Abu Bakar", "family": "Salim", "initials": "A. B. S."} {"name": "Abu Bakr Al Baghdadi, MD", "given": "Abu Bakr", "family": "Al Baghdadi", "suffix": "MD", "initials": "A. B. B."} +{"name": "Abu Karim", "given": "Abu", "family": "Karim", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "A. K."} {"name": "Abu-'l-Fidāʾ Ismāʿīl Ibn-ʿAlī", "given": "Abu-'l-Fidāʾ", "middle": "Ismāʿīl", "family": "Ibn-ʿAlī", "initials": "A. I. I."} {"name": "Abu-'l-Qāsim Maslama Ibn-Aḥmad al-Maǧrīṭī", "given": "Abu-'l-Qāsim", "middle": "Maslama Ibn-Aḥmad", "family": "al-Maǧrīṭī", "initials": "A. M. I. a."} {"name": "Abū-Bakr aš-Šiblī", "given": "Abū-Bakr", "family": "aš-Šiblī", "initials": "A. a."} @@ -121,6 +122,7 @@ {"name": "Ali Ahmad oglu", "given": "Ali", "middle": "Ahmad", "family": "oglu", "initials": "A. A. o."} {"name": "Ali Amina", "order": "FAMILY_FIRST", "given": "Amina", "family": "Ali", "initials": "A. A."} {"name": "Ali Juma Hamisi", "given": "Ali", "middle": "Juma", "family": "Hamisi", "initials": "A. J. H."} +{"name": "Ali Kara Oğlu", "given": "Ali", "middle": "Kara", "family": "Oğlu", "initials": "A. K. O."} {"name": "Ali, Amina", "given": "Amina", "family": "Ali", "initials": "A. A."} {"name": "Alice Rühle-Gerstel", "given": "Alice", "family": "Rühle-Gerstel", "initials": "A. R."} {"name": "Alina", "given": "Alina", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "A."} @@ -438,6 +440,7 @@ {"name": "Carlos Sáenz Echeverría", "given": "Carlos", "middle": "Sáenz", "family": "Echeverría", "initials": "C. S. E."} {"name": "Carlos Uribe Cordovez", "given": "Carlos", "middle": "Uribe", "family": "Cordovez", "initials": "C. U. C."} {"name": "Carlos Zabala", "given": "Carlos", "family": "Zabala", "initials": "C. Z."} +{"name": "Carmen Díaz Vda. de Mora", "given": "Carmen", "middle": "Díaz Vda.", "family": "de Mora", "initials": "C. D. V. M."} {"name": "Carnarvon, George Edward Stanhope Molyneux Herbert of", "given": "George", "middle": "Edward Stanhope Molyneux Herbert of", "family": "Carnarvon", "initials": "G. E. S. M. H. C."} {"name": "Carod i", "given": "Carod", "suffix": "i", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "C."} {"name": "Carod i Rovira", "given": "Carod", "middle": "i", "family": "Rovira", "initials": "C. i. R."} @@ -530,8 +533,10 @@ {"name": "Daniel Ayala Pérez", "given": "Daniel", "middle": "Ayala", "family": "Pérez", "initials": "D. A. P."} {"name": "Daniel Bautista Rocha", "given": "Daniel", "middle": "Bautista", "family": "Rocha", "initials": "D. B. R."} {"name": "David Ben Gurion", "given": "David", "middle": "Ben", "family": "Gurion", "initials": "D. B. G."} +{"name": "David arap Kirui", "given": "David", "middle": "arap", "family": "Kirui", "initials": "D. a. K."} {"name": "David zu Sonnegg von Ungnad von Weissenwolf", "given": "David", "middle": "zu Sonnegg von Ungnad", "family": "von Weissenwolf", "initials": "D. S. U. W."} {"name": "Davis Royce, Ed", "given": "Davis", "family": "Royce", "suffix": "Ed", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "D. R."} +{"name": "Daw Thida", "given": "Daw", "family": "Thida", "initials": "D. T."} {"name": "Daði Freyr Pétursson", "given": "Daði", "middle": "Freyr", "family": "Pétursson", "initials": "D. F. P."} {"name": "De Groot", "family": "De Groot", "initials": "G."} {"name": "De La Cruz, Ed", "given": "Ed", "family": "De La Cruz", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "E. C."} @@ -1055,6 +1060,7 @@ {"name": "Gylfi Sigurðsson", "given": "Gylfi", "family": "Sigurðsson", "initials": "G. S."} {"name": "Gábor, Andor", "given": "Andor", "family": "Gábor", "initials": "A. G."} {"name": "Gössmann, Elisabeth", "given": "Elisabeth", "family": "Gössmann", "initials": "E. G."} +{"name": "H. Budi Santoso", "given": "H.", "middle": "Budi", "family": "Santoso", "initials": "H. B. S."} {"name": "Habib Pacha es-Saad", "given": "Habib", "middle": "Pacha", "family": "es-Saad", "initials": "H. P. e."} {"name": "Hafis al-Assad", "given": "Hafis", "family": "al-Assad", "initials": "H. a."} {"name": "Hagen, Hermann von", "given": "Hermann", "family": "von Hagen", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "H. H."} @@ -1086,6 +1092,7 @@ {"name": "Haren, Willem van", "given": "Willem", "family": "van Haren", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "W. H."} {"name": "Harietta Keopuolani Nahi'ena'ena", "given": "Harietta", "middle": "Keopuolani", "family": "Nahi'ena'ena", "initials": "H. K. N."} {"name": "Harms, Claus", "given": "Claus", "family": "Harms", "initials": "C. H."} +{"name": "Harpreet Kaur Dhillon", "given": "Harpreet", "middle": "Kaur", "family": "Dhillon", "initials": "H. K. D."} {"name": "Harrieta Keōpūolani Nāhiʻenaʻena", "given": "Harrieta", "middle": "Keōpūolani", "family": "Nāhiʻenaʻena", "initials": "H. K. N."} {"name": "Hasani Maria", "order": "FAMILY_FIRST", "given": "Maria", "family": "Hasani", "initials": "M. H."} {"name": "Hasani, Maria", "given": "Maria", "family": "Hasani", "initials": "M. H."} @@ -1093,7 +1100,9 @@ {"name": "Hashimoto, Chikanobu", "given": "Chikanobu", "family": "Hashimoto", "initials": "C. H."} {"name": "Hassan", "given": "Hassan", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "H."} {"name": "Hassan", "order": "FAMILY_FIRST", "family": "Hassan", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "H."} +{"name": "Hassan B. Yusof", "given": "Hassan", "middle": "B.", "family": "Yusof", "initials": "H. B. Y."} {"name": "Hassan Mohamad Ali", "given": "Hassan", "middle": "Mohamad", "family": "Ali", "initials": "H. M. A."} +{"name": "Hassan bin Yusof", "given": "Hassan", "family": "bin Yusof", "initials": "H. Y."} {"name": "Hassan, Mohamad Ahmad Ali", "given": "Mohamad", "middle": "Ahmad Ali", "family": "Hassan", "initials": "M. A. A. H."} {"name": "Haukur Ágústsson", "given": "Haukur", "family": "Ágústsson", "initials": "H. Á."} {"name": "Hebe de Bonafini", "given": "Hebe", "family": "de Bonafini", "initials": "H. B."} @@ -1130,6 +1139,7 @@ {"name": "His Holiness", "title": "His", "family": "Holiness", "ambiguities": ["TITLE_OR_NAME"], "initials": "H."} {"name": "His Holiness the Dalai Lama", "title": "His Holiness the Dalai", "family": "Lama", "ambiguities": ["TITLE_OR_NAME"], "initials": "L."} {"name": "Hisham Ibrahim, CPA, CFA", "given": "Hisham", "family": "Ibrahim", "suffix": "CPA, CFA", "initials": "H. I."} +{"name": "Hodan Farah Warsame", "given": "Hodan", "middle": "Farah", "family": "Warsame", "initials": "H. F. W."} {"name": "Hon Solo", "title": "Hon", "family": "Solo", "initials": "S."} {"name": "Hon. Barrington P. Doe-Ray, Jr.", "title": "Hon.", "given": "Barrington", "middle": "P.", "family": "Doe-Ray", "suffix": "Jr.", "initials": "B. P. D."} {"name": "Hon. Charles J. Siragusa", "title": "Hon.", "given": "Charles", "middle": "J.", "family": "Siragusa", "initials": "C. J. S."} @@ -1206,6 +1216,7 @@ {"name": "Ivan", "given": "Ivan", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "I."} {"name": "Ivan", "order": "FAMILY_FIRST", "family": "Ivan", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "I."} {"name": "Ivan Ivanov", "given": "Ivan", "family": "Ivanov", "initials": "I. I."} +{"name": "Ivan Petrov Dimitrov", "given": "Ivan", "middle": "Petrov", "family": "Dimitrov", "initials": "I. P. D."} {"name": "Ivan Tham Jun Hoe", "given": "Ivan", "middle": "Tham Jun", "family": "Hoe", "initials": "I. T. J. H."} {"name": "Ivanov Ivan", "given": "Ivanov", "family": "Ivan", "initials": "I. I."} {"name": "Ivanov Ivan Ivanovich", "given": "Ivanov", "middle": "Ivan", "family": "Ivanovich", "initials": "I. I. I."} @@ -1658,6 +1669,7 @@ {"name": "Josep Maria Tarridas i Barri", "given": "Josep", "middle": "Maria", "family": "Tarridas i Barri", "initials": "J. M. T. B."} {"name": "Josep Vergés i Vallmajor", "given": "Josep", "family": "Vergés i Vallmajor", "initials": "J. V. V."} {"name": "Josep i Rovira", "given": "Josep", "middle": "i", "family": "Rovira", "initials": "J. i. R."} +{"name": "Joseph ole Sankale", "given": "Joseph", "middle": "ole", "family": "Sankale", "initials": "J. o. S."} {"name": "Joset, Theodor", "given": "Theodor", "family": "Joset", "initials": "T. J."} {"name": "José Antonio Nieves Conde", "given": "José", "middle": "Antonio Nieves", "family": "Conde", "initials": "J. A. N. C."} {"name": "José Antonio Osorio Lizarazo", "given": "José", "middle": "Antonio Osorio", "family": "Lizarazo", "initials": "J. A. O. L."} @@ -1789,6 +1801,7 @@ {"name": "Júlíus Agnarsson", "given": "Júlíus", "family": "Agnarsson", "initials": "J. A."} {"name": "Jānis", "given": "Jānis", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "J."} {"name": "Jānis", "order": "FAMILY_FIRST", "family": "Jānis", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "J."} +{"name": "K. Sivakumar", "given": "K.", "family": "Sivakumar", "initials": "K. S."} {"name": "KALAM Alɛ Mustafa", "order": "FAMILY_FIRST", "given": "Alɛ", "middle": "Mustafa", "family": "KALAM", "initials": "A. M. K."} {"name": "KANSULO Iiɖa", "order": "FAMILY_FIRST", "given": "Iiɖa", "family": "KANSULO", "initials": "I. K."} {"name": "Kajal Patel Hiring Globally", "given": "Kajal", "middle": "Patel Hiring", "family": "Globally", "initials": "K. P. H. G."} @@ -1820,6 +1833,7 @@ {"name": "Katrín Jakobsdóttir", "given": "Katrín", "family": "Jakobsdóttir", "initials": "K. J."} {"name": "Katrín Júlíusdóttir", "given": "Katrín", "family": "Júlíusdóttir", "initials": "K. J."} {"name": "Katy Mané", "given": "Katy", "family": "Mané", "initials": "K. M."} +{"name": "Kavitha a/p Raman", "given": "Kavitha", "middle": "a/p", "family": "Raman", "initials": "K. a. R."} {"name": "Kaya Yağız Can", "order": "FAMILY_FIRST", "given": "Yağız", "middle": "Can", "family": "Kaya", "initials": "Y. C. K."} {"name": "Kaya, Yağız Can", "given": "Yağız", "middle": "Can", "family": "Kaya", "initials": "Y. C. K."} {"name": "Kazlauskienė Irena", "order": "FAMILY_FIRST", "given": "Irena", "family": "Kazlauskienė", "initials": "I. K."} @@ -1838,8 +1852,10 @@ {"name": "Kevin", "order": "FAMILY_FIRST", "family": "Kevin", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "K."} {"name": "Khaled el-Hassani ben el-Hachemi", "given": "Khaled", "middle": "el-Hassani ben", "family": "el-Hachemi", "initials": "K. e. b. e."} {"name": "Kho Liang Ie", "given": "Kho", "middle": "Liang", "family": "Ie", "initials": "K. L. I."} +{"name": "Khun Malee", "given": "Khun", "family": "Malee", "initials": "K. M."} {"name": "Khun Sa", "given": "Khun", "suffix": "Sa", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "K."} {"name": "Ki, Tomonori", "given": "Tomonori", "family": "Ki", "initials": "T. K."} +{"name": "Kim Min Ho", "order": "FAMILY_FIRST", "given": "Min", "middle": "Ho", "family": "Kim", "initials": "M. H. K."} {"name": "Kim, Jr.", "family": "Kim", "suffix": "Jr.", "initials": "K."} {"name": "Kim김민준씨, MA", "family": "Kim김민준", "suffix": "씨, MA", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "K."} {"name": "King Curtis", "title": "King", "given": "Curtis", "initials": "C."} @@ -1934,6 +1950,7 @@ {"name": "Liberty Hyde Bailey", "given": "Liberty", "middle": "Hyde", "family": "Bailey", "initials": "L. H. B."} {"name": "Lilja Alfreðsdóttir", "given": "Lilja", "family": "Alfreðsdóttir", "initials": "L. A."} {"name": "Lim Boo Liat", "given": "Lim", "middle": "Boo", "family": "Liat", "initials": "L. B. L."} +{"name": "Lim Mei Ling Jessica", "order": "FAMILY_FIRST", "given": "Mei", "middle": "Ling Jessica", "family": "Lim", "initials": "M. L. J. L."} {"name": "Lipset, Seymour Martin", "given": "Seymour", "middle": "Martin", "family": "Lipset", "initials": "S. M. L."} {"name": "Lisa Schmidt, MBA", "given": "Lisa", "family": "Schmidt", "suffix": "MBA", "initials": "L. S."} {"name": "Lisandro Leyva Mazuera", "given": "Lisandro", "middle": "Leyva", "family": "Mazuera", "initials": "L. L. M."} @@ -2012,6 +2029,7 @@ {"name": "Ma III, Jack Jr", "given": "Jack", "family": "Ma", "suffix": "III, Jr", "initials": "J. M."} {"name": "Ma, Andrew", "given": "Andrew", "family": "Ma", "initials": "A. M."} {"name": "Ma, Jack", "given": "Jack", "family": "Ma", "initials": "J. M."} +{"name": "Ma. Teresa Cruz Bautista", "title": "Ma.", "given": "Teresa", "middle": "Cruz", "family": "Bautista", "initials": "T. C. B."} {"name": "Maazị Christopher Chukwudike Amadi MP", "given": "Maazị", "middle": "Christopher Chukwudike", "family": "Amadi", "suffix": "MP", "initials": "M. C. C. A."} {"name": "Mac Miller", "given": "Mac", "family": "Miller", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "M. M."} {"name": "Mac a’ Ghobhainn Chorùna, Mgr. Dòmhnall Iain Bàn am post", "order": "FAMILY_FIRST", "title": "Mgr.", "given": "Dòmhnall", "middle": "Iain Bàn", "family": "Mac a’ Ghobhainn Chorùna", "suffix": "am post", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "D. I. B. a. G. C."} @@ -2183,6 +2201,7 @@ {"name": "Mgr. Dòmhnall Iain Bàn Mac a’ Ghobhainn Chorùna am post", "title": "Mgr.", "given": "Dòmhnall", "middle": "Iain Bàn", "family": "Mac a’ Ghobhainn Chorùna", "suffix": "am post", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "D. I. B. a. G. C."} {"name": "Mgr. Ing. Anna Karolína Eva Kristína von Kant Nováková Predná, CSc.", "title": "Mgr. Ing.", "given": "Anna", "middle": "Karolína Eva Kristína", "family": "von Kant Nováková Predná", "suffix": "CSc.", "initials": "A. K. E. K. K. N. P."} {"name": "Mgr. Ing. von Kant Nováková Predná Anna Karolína Eva Kristína, CSc.", "order": "FAMILY_FIRST", "title": "Mgr. Ing.", "given": "Kant", "middle": "Nováková Predná Anna Karolína Eva Kristína", "family": "von", "suffix": "CSc.", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "K. N. P. A. K. E. K. v."} +{"name": "Michael Wong Kar Ming", "given": "Michael", "middle": "Wong Kar", "family": "Ming", "initials": "M. W. K. M."} {"name": "Miguel García Martínez", "given": "Miguel", "middle": "García", "family": "Martínez", "initials": "M. G. M."} {"name": "Miguel Lanz Duret", "given": "Miguel", "middle": "Lanz", "family": "Duret", "initials": "M. L. D."} {"name": "Miguel Sánchez Pesquera", "given": "Miguel", "middle": "Sánchez", "family": "Pesquera", "initials": "M. S. P."} @@ -2270,6 +2289,7 @@ {"name": "Muniiru", "order": "FAMILY_FIRST", "family": "Muniiru", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "M."} {"name": "Munster, Jan van", "given": "Jan", "family": "van Munster", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "J. M."} {"name": "Murad III.", "given": "Murad", "suffix": "III.", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "M."} +{"name": "Murat Bey", "given": "Murat", "family": "Bey", "initials": "M. B."} {"name": "Muslim Ibn-al-Ḥaǧǧāǧ al-Qušairī", "given": "Muslim", "middle": "Ibn-al-Ḥaǧǧāǧ", "family": "al-Qušairī", "initials": "M. I. a."} {"name": "Muspratt, James", "given": "James", "family": "Muspratt", "initials": "J. M."} {"name": "Mustafa I.", "given": "Mustafa", "family": "I.", "initials": "M. I."} @@ -2368,6 +2388,7 @@ {"name": "Ortega y Gasset, Dr.", "title": "Dr.", "given": "Ortega", "middle": "y", "family": "Gasset", "initials": "O. y. G."} {"name": "Ortega y Gasset, Ed", "given": "Ortega", "middle": "y", "family": "Gasset", "suffix": "Ed", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "O. y. G."} {"name": "Orueta y Duarte, Ricardo de", "given": "Ricardo", "family": "de Orueta y Duarte", "initials": "R. O. D."} +{"name": "Orval, Pierre d'", "given": "Pierre", "middle": "d'", "family": "Orval", "initials": "P. d. O."} {"name": "Orville, Johann Friedrich d'", "given": "Johann", "middle": "Friedrich d'", "family": "Orville", "initials": "J. F. d. O."} {"name": "Ospina Pérez, Mariano", "given": "Mariano", "family": "Ospina Pérez", "initials": "M. O. P."} {"name": "Otto III.", "given": "Otto", "suffix": "III.", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "O."} @@ -2385,6 +2406,7 @@ {"name": "Paku Alam VIII", "given": "Paku", "family": "Alam", "suffix": "VIII", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "P. A."} {"name": "Pan Nowak Tomasz Jan", "order": "FAMILY_FIRST", "given": "Nowak", "middle": "Tomasz Jan", "family": "Pan", "initials": "N. T. J. P."} {"name": "Pan Tomasz Nowak", "given": "Pan", "middle": "Tomasz", "family": "Nowak", "initials": "P. T. N."} +{"name": "Park Ji-hoon ssi", "order": "FAMILY_FIRST", "given": "Ji-hoon", "middle": "ssi", "family": "Park", "initials": "J. s. P."} {"name": "Pascual Ortiz Rubio", "given": "Pascual", "middle": "Ortiz", "family": "Rubio", "initials": "P. O. R."} {"name": "Patricia Terrazas Allen", "given": "Patricia", "middle": "Terrazas", "family": "Allen", "initials": "P. T. A."} {"name": "Patricio Flores Sandoval", "given": "Patricio", "middle": "Flores", "family": "Sandoval", "initials": "P. F. S."} @@ -2398,6 +2420,7 @@ {"name": "Pedro Galindo Galarza", "given": "Pedro", "middle": "Galindo", "family": "Galarza", "initials": "P. G. G."} {"name": "Pedro Infante Torrentera", "given": "Pedro", "middle": "Infante", "family": "Torrentera", "initials": "P. I. T."} {"name": "Pedro Jorba y Gassó", "given": "Pedro", "family": "Jorba y Gassó", "initials": "P. J. G."} +{"name": "Pedro López Ruiz H.", "given": "Pedro", "middle": "López Ruiz", "family": "H.", "initials": "P. L. R. H."} {"name": "Pedro Morales Pino", "given": "Pedro", "middle": "Morales", "family": "Pino", "initials": "P. M. P."} {"name": "Pendeta Zaba", "given": "Pendeta", "family": "Zaba", "initials": "P. Z."} {"name": "Penkauskienė Sofija Rita", "order": "FAMILY_FIRST", "given": "Sofija", "middle": "Rita", "family": "Penkauskienė", "initials": "S. R. P."} @@ -2533,6 +2556,7 @@ {"name": "Rev John A. Kenneth Doe III (Kenny)", "title": "Rev", "given": "John", "middle": "A. Kenneth", "family": "Doe", "suffix": "III", "nickname": "Kenny", "initials": "J. A. K. D."} {"name": "Rev. John A. Kenneth Doe", "title": "Rev.", "given": "John", "middle": "A. Kenneth", "family": "Doe", "initials": "J. A. K. D."} {"name": "Rev. John Smith", "title": "Rev.", "given": "John", "family": "Smith", "initials": "J. S."} +{"name": "Reza Hossein Zadeh", "given": "Reza", "middle": "Hossein", "family": "Zadeh", "initials": "R. H. Z."} {"name": "Ricardo Bodenlle Corral", "given": "Ricardo", "middle": "Bodenlle", "family": "Corral", "initials": "R. B. C."} {"name": "Ricardo Legorreta Vilchis", "given": "Ricardo", "middle": "Legorreta", "family": "Vilchis", "initials": "R. L. V."} {"name": "Ricardo Valderrama Fernández", "given": "Ricardo", "middle": "Valderrama", "family": "Fernández", "initials": "R. V. F."} @@ -2903,8 +2927,11 @@ {"name": "Sulaiman, Salimah", "given": "Salimah", "family": "Sulaiman", "initials": "S. S."} {"name": "Sule", "given": "Sule", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "S."} {"name": "Sule", "order": "FAMILY_FIRST", "family": "Sule", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "S."} +{"name": "Suresh a/l Muthu", "given": "Suresh", "middle": "a/l", "family": "Muthu", "initials": "S. a. M."} {"name": "Surāqa Ibn-Mirdās al-Aṣġar", "given": "Surāqa", "middle": "Ibn-Mirdās", "family": "al-Aṣġar", "initials": "S. I. a."} +{"name": "Suzuki san", "order": "FAMILY_FIRST", "given": "san", "family": "Suzuki", "initials": "s. S."} {"name": "Suzuki, Shōsan", "given": "Shōsan", "family": "Suzuki", "initials": "S. S."} +{"name": "Suzuki-san", "order": "FAMILY_FIRST", "family": "Suzuki-san", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "S."} {"name": "Svarun", "given": "Svarun", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "S."} {"name": "Svarun", "order": "FAMILY_FIRST", "family": "Svarun", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "S."} {"name": "Svavar Guðnason", "given": "Svavar", "family": "Guðnason", "initials": "S. G."} @@ -2920,6 +2947,9 @@ {"name": "Syukri @ Shu Qi Mohd Nor", "given": "Syukri", "middle": "@ Shu Qi Mohd", "family": "Nor", "initials": "S. @. S. Q. M. N."} {"name": "Szabados Máté Bendegúz", "order": "FAMILY_FIRST", "given": "Máté", "middle": "Bendegúz", "family": "Szabados", "initials": "M. B. S."} {"name": "Szabados, Máté Bendegúz", "given": "Máté", "middle": "Bendegúz", "family": "Szabados", "initials": "M. B. S."} +{"name": "Szabó Péter úr", "order": "FAMILY_FIRST", "given": "Péter", "middle": "úr", "family": "Szabó", "initials": "P. ú. S."} +{"name": "Szabó Péterné", "order": "FAMILY_FIRST", "given": "Péterné", "family": "Szabó", "initials": "P. S."} +{"name": "Szabóné Kiss Éva", "order": "FAMILY_FIRST", "given": "Kiss", "middle": "Éva", "family": "Szabóné", "initials": "K. É. S."} {"name": "Szigeti, Joseph", "given": "Joseph", "family": "Szigeti", "initials": "J. S."} {"name": "Sébastien de Brossard", "given": "Sébastien", "family": "de Brossard", "initials": "S. B."} {"name": "Séverine", "given": "Séverine", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "S."} @@ -2975,9 +3005,11 @@ {"name": "Torres, Ana", "given": "Ana", "family": "Torres", "initials": "A. T."} {"name": "Tounens, Antoine de", "given": "Antoine", "family": "de Tounens", "initials": "A. T."} {"name": "Traberth, Julie", "given": "Julie", "family": "Traberth", "initials": "J. T."} +{"name": "Tran Thi Mai", "order": "FAMILY_FIRST", "given": "Thi", "family": "Tran", "suffix": "Mai", "initials": "T. T."} {"name": "Tschagribeg", "given": "Tschagribeg", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "T."} {"name": "Tschurtschenthaler, Anton von", "given": "Anton", "family": "von Tschurtschenthaler", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "A. T."} {"name": "Tunde Seun Okeke", "given": "Tunde", "middle": "Seun", "family": "Okeke", "initials": "T. S. O."} +{"name": "U Kyaw Win", "given": "U", "middle": "Kyaw", "family": "Win", "initials": "U. K. W."} {"name": "U. S. Grant", "given": "U.", "middle": "S.", "family": "Grant", "initials": "U. S. G."} {"name": "U.S. District Judge Marc Thomas Treadwell", "given": "U.S.", "middle": "District Judge Marc Thomas", "family": "Treadwell", "initials": "U. D. J. M. T. T."} {"name": "UNILEVER LTD", "given": "UNILEVER", "family": "LTD", "initials": "U. L."} @@ -3021,6 +3053,7 @@ {"name": "Van Rooten, Luis", "given": "Luis", "family": "Van Rooten", "initials": "L. R."} {"name": "Van der Merwe Jan Koos", "order": "FAMILY_FIRST", "given": "der Merwe Jan Koos", "family": "Van", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "d. M. J. K. V."} {"name": "Van der Merwe, Jan Koos", "given": "Jan", "middle": "Koos", "family": "Van der Merwe", "initials": "J. K. M."} +{"name": "Van der Walt", "given": "Van", "family": "der Walt", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "V. W."} {"name": "Varano, Costanza da", "given": "Costanza", "family": "da Varano", "ambiguities": ["PARTICLE_OR_GIVEN"], "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."} @@ -3073,6 +3106,7 @@ {"name": "Wang M.Eng.", "given": "Wang", "suffix": "M.Eng.", "ambiguities": ["GIVEN_OR_FAMILY"], "initials": "W."} {"name": "Wang Ma PhD", "given": "Wang", "family": "Ma", "suffix": "PhD", "ambiguities": ["SUFFIX_OR_NAME"], "initials": "W. M."} {"name": "Wang, Zhaojun", "given": "Zhaojun", "family": "Wang", "initials": "Z. W."} +{"name": "Wanjiru wa Kamau", "given": "Wanjiru", "middle": "wa", "family": "Kamau", "initials": "W. w. K."} {"name": "Washington Jr. MD, Franklin", "given": "Franklin", "family": "Washington", "suffix": "Jr. MD", "initials": "F. W."} {"name": "Watson John Hamish", "order": "FAMILY_FIRST", "given": "John", "middle": "Hamish", "family": "Watson", "initials": "J. H. W."} {"name": "Watson John Hámish", "order": "FAMILY_FIRST", "given": "John", "middle": "Hámish", "family": "Watson", "initials": "J. H. W."} @@ -3104,6 +3138,7 @@ {"name": "Willemse, Bertus Wilbers Henri Retief", "given": "Bertus", "middle": "Wilbers Henri Retief", "family": "Willemse", "initials": "B. W. H. R. W."} {"name": "Willemse, Heidi Johannes", "given": "Heidi", "middle": "Johannes", "family": "Willemse", "initials": "H. J. W."} {"name": "Willington Baena Ortiz", "given": "Willington", "middle": "Baena", "family": "Ortiz", "initials": "W. B. O."} +{"name": "Wing Lau", "title": "Wing", "family": "Lau", "initials": "L."} {"name": "Winghe, Jodocus van", "given": "Jodocus", "family": "van Winghe", "ambiguities": ["PARTICLE_OR_GIVEN"], "initials": "J. W."} {"name": "Witte, Jean Joseph Antoine Marie de", "given": "Jean", "middle": "Joseph Antoine Marie", "family": "de Witte", "initials": "J. J. A. M. W."} {"name": "Wićazowa, Jěwa-Marja Hańža", "given": "Jěwa-Marja", "middle": "Hańža", "family": "Wićazowa", "initials": "J. H. W."} From 9d3ee1ed31e7583377a88e9388ab0df3f97e00d3 Mon Sep 17 00:00:00 2001 From: Derek Gulbranson Date: Fri, 16 Oct 2026 19:29:22 -0700 Subject: [PATCH 2/2] Give the right reasons a fields file was declined; load siblings by path Review of #691: the scorer already handles a patronymic (PENDING_ROLES) and expects an empty family where none is stated, so neither example showed what a fields file could not say. The ones that do are a father's or grandfather's name, an honorific that is not a title and a married form, and some expectations are undecided. The order docstring now names the two orders a shape declares; Kaur is traditional, not universal; Tran Thi Mai's note says Mai is a suffix acronym under either order. The builder loads conventions.py and shapes.py by path, as snapshot.load_shapes does, instead of putting tools/differential/ on sys.path for the rest of a test run. Co-Authored-By: Claude Opus 5.5 --- tools/differential/README.md | 21 ++++++++++--------- .../differential/build_conventions_corpus.py | 21 ++++++++++++++----- tools/differential/conventions.py | 19 ++++++++++------- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/tools/differential/README.md b/tools/differential/README.md index bbc4c8fe..3faf01fe 100644 --- a/tools/differential/README.md +++ b/tools/differential/README.md @@ -302,12 +302,12 @@ uv run python tools/differential/build_cjk_corpus.py ``` Every distinct CJK-bearing `text` in `tests/v2/cases.py`, `tolerated` -rows included. The generated corpora (`corpus_cjk`, `corpus_conventions`, -`corpus_rules`, `corpus_shapes`) are each pinned by `tests/v2/test_corpora.py` against -their generator's selection, so a case row, a rules.md example or a -`conventions.py` row added -without regenerating fails the suite instead of silently narrowing -what the snapshot watches. +rows included. The generated corpora (`corpus_cjk`, +`corpus_conventions`, `corpus_rules`, `corpus_shapes`) are each pinned +by `tests/v2/test_corpora.py` against their generator's selection, so a +case row, a rules.md example or a `conventions.py` row added without +regenerating fails the suite instead of silently narrowing what the +snapshot watches. `corpus_conventions.jsonl` is generated from `conventions.py`, a table whose rows record the tradition, the convention a name exercises, and @@ -318,10 +318,11 @@ uv run python tools/differential/build_conventions_corpus.py ``` That expectation is a note, not a pin, and nothing scores against -it: many are stated in terms the model cannot express yet (a -patronymic, a name with no family name), and a fields file would -read each such unstated part as an empty role (#686). A row whose -reading is settled graduates to `tests/v2/cases.py`. The names are +it: many are stated in terms no field states (a father's or +grandfather's name, an honorific that is not a title, a married form), +some are undecided, and a fields file must state every part, since the +scorer reads an unstated one as an empty role (#686). A row whose +reading is settled can graduate to `tests/v2/cases.py`. The names are invented, never copied from the references the conventions come from. diff --git a/tools/differential/build_conventions_corpus.py b/tools/differential/build_conventions_corpus.py index 0ec1dec1..677e616b 100644 --- a/tools/differential/build_conventions_corpus.py +++ b/tools/differential/build_conventions_corpus.py @@ -15,17 +15,28 @@ """ from __future__ import annotations +import importlib.util import json -import sys from pathlib import Path +from types import ModuleType HERE = Path(__file__).resolve().parent -sys.path.insert(0, str(HERE)) +OUT = HERE / "corpus_conventions.jsonl" -from conventions import CONVENTIONS # noqa: E402 -from shapes import SHAPES # noqa: E402 -OUT = HERE / "corpus_conventions.jsonl" +def _load(stem: str) -> ModuleType: + """A sibling module, loaded by path as snapshot.load_shapes does: + tools/ is not a package, and putting tools/differential/ on sys.path + would let its modules shadow bare imports for the rest of a test run.""" + spec = importlib.util.spec_from_file_location(f"_{stem}", HERE / f"{stem}.py") + assert spec and spec.loader + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +CONVENTIONS = _load("conventions").CONVENTIONS +SHAPES = _load("shapes").SHAPES def _shape_for(order: str) -> int: diff --git a/tools/differential/conventions.py b/tools/differential/conventions.py index a70b62a7..71e4bf45 100644 --- a/tools/differential/conventions.py +++ b/tools/differential/conventions.py @@ -11,15 +11,16 @@ `expect` is a NOTE, not a pin: what a reader who knows the convention would take each part to be, often in terms the model cannot express yet -(a patronymic, a name with no family name, an honorific that is not a -title). Nothing scores the parser against it (#686 decided against a -fields file). Today's reading is deliberately not recorded here either: +(a father's or grandfather's name, an honorific that is not a title, a +married form), and sometimes left undecided (`H. Budi Santoso`). Nothing +scores the parser against it (#686 decided against a fields file). Today's reading is deliberately not recorded here either: snapshot.jsonl holds it, and a second copy would go stale. A row whose reading is settled can graduate to tests/v2/cases.py, where it becomes a contract. -`order` is a public nameparser constant name, as in shapes.py; None is -the default order. +`order` names an order some shapes.py shape declares, `"FAMILY_FIRST"` +or `"FAMILY_FIRST_GIVEN_LAST"`; the default order is None, not +`"GIVEN_FIRST"`, which no shape declares. """ from typing import NamedTuple @@ -39,8 +40,8 @@ class Convention(NamedTuple): "given names, not a family name"), Convention("Sikh", "religious name between given and family name", "Harpreet Kaur Dhillon", None, - "given Harpreet; Kaur is the religious name every Sikh woman bears, " - "written as a surname when no family name is; family Dhillon"), + "given Harpreet; Kaur is the religious name Sikh women traditionally " + "take, written as a surname when no family name is; family Dhillon"), Convention("Tamil", "father's given name as a leading initial", "K. Sivakumar", None, "K. is the father's given name; Sivakumar is the person's own given " @@ -72,7 +73,9 @@ class Convention(NamedTuple): Convention("Vietnamese", "Thi as the female middle name", "Tran Thi Mai", "FAMILY_FIRST", "family Tran; middle Thi; given Mai, which the convention writes " - "last (the order FAMILY_FIRST_GIVEN_LAST names)"), + "last (the order FAMILY_FIRST_GIVEN_LAST names; read under " + "FAMILY_FIRST as the issue measured it); Mai is also a " + "suffix acronym, so either order reads it as a suffix"), Convention("Bulgarian", "patronymic between given and family name", "Ivan Petrov Dimitrov", None, "given Ivan; Petrov his patronymic, from his father Petar; family "