Skip to content

Read a Turkic marker ending three name words with the father's name as the family (#1187) - #1366

Merged
derek73 merged 7 commits into
masterfrom
feat/issue-1187-father-marker-family
Nov 13, 2026
Merged

derek73 merged 7 commits into
masterfrom
feat/issue-1187-father-marker-family

Conversation

@derek73

@derek73 derek73 commented Nov 12, 2026 •

Copy link
Copy Markdown
Owner

Closes #1187. Refs #1253.

Under Turkic handling (locales.TR_AZ, or PatronymicRule.TURKIC), a name of exactly three name words that ends in a standalone patronymic marker now reads the father's name and the marker together as the family. The patronymic view already held the same two words.

from nameparser import parser_for, locales
n = parser_for(locales.TR_AZ).parse("Бекмырза Чолпонбай уулу")
n.given, n.family, n.patronymic   # ('Бекмырза', 'Чолпонбай уулу', 'Чолпонбай уулу')

1.4.0 (with Turkic handling) through 3.0.1 read middle Чолпонбай, family уулу. The group suggester now votes Turkic for the same shape, so a list of such names gets the rule.

This is the second leaf of #1253's decision. Its first statement: family is the name a convention files a person under, and a Kyrgyz name with no surname files under Father uulu.

The rule (rules/O2, the Turkic rotation)

  • Scope. It keeps the four-word rotation's scope: no comma, the default given-first order standing (a declared family-first order stands, as O1's scope says), and titles, suffixes and nicknames aside.
  • The marker must be the last name word. The code checks this by position as well as by role. With the East Slavic rule also on, O1 may have rotated a marker-first name (Уулу Аскар Бакытович keeps family Уулу, patronymic Бакытович). Review found that the first version got this wrong.
  • Unchanged shapes (each a boundary example in rules/O2 and a test row):
    • two name words: Cavad oğlu → family oğlu;
    • five or more;
    • a given name that P5 binds from two words: Abdul Rahman Ahmad oglu → family oglu;
    • a suffix comma: Aidai Mederbek kyzy, PhD → family kyzy.
  • Precedence over O6. The middle word is taken first, so under two_family_names Ali Hasan oglu reads one family unit (surname1 Hasan oglu) where it read two.
  • The old O2 boundary example "Ali Ahmad oglu" [tr_az] → family="oglu" moves. Its 2026-07-02 decisions entry gets a superseded note, not a rewrite.

Gate: measured before the code (2026-11-12)

The parliament figures in this PR were first taken on the opensanctions-parliaments fetch of 2026-11-12 with 23 datasets (24,066 names). They were re-taken after master (with #1368) was merged in, on the 24-dataset fetch of the same day (24,302 records). Every Turkic chamber's count is unchanged, and the Turkic chambers' counts also match the 2026-11-08 fetch. Under TR_AZ and TR_AZ+RU, the parliaments' readings against master still move exactly five names: the four Kyrgyz names and id_dpr's Y. JACKI ULY. Other figures come from the fielded local corpora:

Source Three name words ending in a marker Other shapes
kg_jogorku_kenesh (90) 4: 3 уулу, 1 кызы the rest write a Russian-style patronymic and a surname
az_parliament (124) 0 121 of four words, SURNAME Given Father oğlu
uz_senate, uz_legislative_chamber, tm_mejlis 0 four words only
kz_mazhilis, kz_senate 0 none
ORCID family boxes holding the marker KG 448 two-word Father kyzy/uulu, 2 the marker alone; UZ 28 two-word UZ 23 and AZ 6 of three (Surname Father qizi)
PSC surname boxes, Kyrgyz all 12 records: Father Uulu / Father Kyzy
  • No chamber writes a two-word or a five-word name ending in a marker.

Decisions for the maintainer

  1. Azerbaijani (Should a Kyrgyz name read Father uulu as the family? (Бекмырза Чолпонбай уулу gives family уулу) #1187's first question). No cached source writes Given Father oğlu without a surname except JRC's Russian spelling of Polad Bülbüloğlu, whose surname is exactly the father's name and the marker. Nothing measured argues for splitting the rule by language, so it reads all Turkic markers alike.

  2. Two words (its second question) stay as they were:

    • PSC's Turkish Ahmed Oglu and ORCID's Gunel Kizi file the marker as the surname.
    • R9 already reads a two-word name whole as the patronymic.
  3. Five words: no instance anywhere, so they keep the positional reading.

  4. The group suggester votes for the shape the rule reads (item 6 lists where it is wider), as decided in coordination: one condition in _suggest._patronymic, so a three-word name with the marker last votes Turkic. Edge rows cover two, three, four and five words, a family comma and a maiden clause. A maiden clause already voted on master, through the four-word shape, and R9's Turkic arm reads it. Nothing else in _suggest.py changes; the Should an ALL-CAPS word in a mixed-case name mark the family name? DUPONT Jean gives given DUPONT #659 worker's second PR touches a different function there.

  5. Matching cost. Under the pack, a father's name written as an initial now conflicts: Ali Ahmad oglu / Ali A. oglu reads family family-initial, which is opt-in. Before, the initial sat in the middle and the pair was consistent. In exchange, Ali Ahmad oglu / Ali Ahmad and the Kyrgyz name with or without its marker become consistent (part-of-other).

  6. Where the vote is wider than the rule (accepted, recorded). Both Turkic arms of _patronymic count the words _name_words keeps, not O2's name words. So each of these votes turkic on this head and the rule leaves the name as it was:

    • a nickname counted as a word: Aichurok "Aika" kyzy, Aichurok (Aika) kyzy, and a marker in brackets, Ali Ahmad (oglu);
    • a given name P5 binds from two words: Abdul Rahman oglu, Abu Bakr uulu (four words: Abdul Rahman Ahmad oglu);
    • a suffix comma: Aichurok Ergeshali kyzy, PhD (four words: Aliyev Ilham Heydar oglu, PhD);
    • a final full stop: Aichurok Ergeshali Kyzy. (four words: Aliyev Ilham Heydar oglu.).

    The four-word arm already had all four gaps on master; the three-word ones are new here. On master, a four-word name holding a nickname was a gap too. Here its three name words are the shape the rule now reads (Aliyev Ilham "Ali" oglu → family Ilham oglu). The gap is harmless: a group of five such names is suggested patronymic_rules={TURKIC} where master suggests nothing, and applying it reads every name as before. tests/v2/test_suggest.py pins each shape on both arms, and decisions/group-suggestion's Should a Kyrgyz name read Father uulu as the family? (Бекмырза Чолпонбай уулу gives family уулу) #1187 entry records them. Narrowing the vote to the rule's name words is a follow-up candidate.

    • Proposed, not done: closing the final stop exactly. The rule tests the marker with is_patronymic_marker(token.text), on the word as written, so oglu. is never a marker there. _patronymic tests it on the stop-stripped bare. Testing the Turkic arms' markers on words instead would make the vote match the rule's predicate for that shape. That is two conditions, with no new machinery; the East Slavic arm keeps reading past the stop.

Observed, not addressed here

  • Parser.revise empties the patronymic view on these names; it already did for the four-word name on master.
  • Aichurok kyzy kyzy reads family kyzy kyzy under TR_AZ; no name doubles the marker.

What moved

  • Corpus readings. Ran config_diff.py diff default plain:TR_AZ plain:TR_AZ+RU --committed --local all --match <the marker alternation stated in decisions/O2> with --readings in both trees and compared line by line, over the 947 names both trees hold.
    • Default: 0 moved.
    • TR_AZ: 489, every one middle → family. 468 are Kyrgyz; the rest are Uzbek, Kazakh and Azerbaijani names of the same shape, plus the committed conventions row Ali Kara Oğlu.
    • TR_AZ+RU: the same 489.
  • Field agreement, local_agreement.py --locale tr_az --base <master>:
    • PSC: 16 progress, 0 regressions.
    • PatentsView: no change.
    • ORCID: 458 progress, 2 regressions, 4 changed. The 2 regressions are holders who put the father's name in the given box and the marker alone in the family box.
  • CLDR per-pack view: TR_AZ 39/48, unchanged.
  • Snapshot: no reading moves. It gains the new rules examples' default readings, from the rules-corpus rebuild.
  • suggest_measure.py --base (this tree's comparator on both sides): 5 cells moved, none in the population rows (the same-order rows are unchanged).
    • The TURKIC table's kg_jogorku_kenesh row: {T} and {E,T} 86/90 → 90/90.
    • kg_jogorku_kenesh's rule votes, 85 for and 0 against → 85 for and 4 against, under both bases. The list is still decided East Slavic.
    • id_dpr's 0/0 → 0/1 under both bases (Y. JACKI ULY), still undecided.
    • The comparator changed too. A family-last list's name had been scored by its last word, the marker alone; it now takes the father's name and the marker for a three-word name ending in one. So against the table recorded in decisions/group-suggestion, nothing, {E} and suggest read 86/90, and {T} and {E,T} stay 90/90.
    • The harness proof holds: every row written against its base reads 0%, and every row in its base's order 100%. No figure quoted in Parser.suggest's docstring, docs/suggest.rst or decisions/group-suggestion moves.

Checks

  • uv run pytest with the ja extra, on the head (69e11b9): 46,071 passed. Without it, on the first commit: 45,999 passed. Python 3.15 in its own environment: 45,999 passed.
  • uv run pytest -n0 -m serial: 35 passed.
  • uv run mypy, uv run ruff check, tools/vocab/build.py --check: clean.
  • sphinx-build -b doctest docs and -W -b html: clean.
  • Every condition of the new branch has a row in _TURKIC_THREE (tests/v2/pipeline/test_post_rules.py) or a test beside it that fails when the condition is removed. Each was checked by mutation.

Reviews

Each review ran as a subagent in its own detached worktree on the pushed head, with a read-only master checkout beside it.

Round Review Found Done
1 (656be21) code-reviewer A real bug: with RU and TR_AZ both on, O1 rotated a marker-first name (Уулу Аскар Бакытович), and the new branch then folded the patronymic into that family. Also: the suggester's vote was narrower than the rule. The matching cost for a father's name written as an initial was unrecorded. A boundary example contradicted O2's statement, and O2's Signal line was stale. The marker must now be the last name word, with a test that fails without the check. The suggester edit landed after coordination. The matching cost is recorded.
1 design-docs-reviewer The superseded note on the TURKIC table described the move backwards. The bound-given-name example contradicted O2. O6 and O7 contradicted the new reading, and O2 lacked a Precedence clause. Counts did not reproduce (488, 40,061, ORCID 370 boxes). The SUPERSEDES line was missing. Every one fixed. The counts were re-taken with stated recipes: 489 moves, 448 boxes; the 370 had missed Cyrillic.
1 comment-analyzer The same TURKIC-table reversal and the same boundary example. The suggester's prose claimed four words. The release log said "any name of three words", and the comparator comment had wrong counts and a wider reach than the rule. All fixed; the comparator now reads exactly three words.
1 pr-test-analyzer The O1-then-O2 chain bug (also found by the code review). The len(families) == 1 condition was unguarded. The _turkic_truth arm was untested. The O6-split concern had lost its only row. NFD and all-caps markers were unpinned. The NFD line in decisions/O2's Standing was stale. Rows and tests added for each, and the Standing line corrected.
2 (225d238) code-reviewer No blocker. Three figures: the name count, uz_senate's Cyrillic spellings being aliases, and the release log's 1.4.0 wording. Fixed in 3fdf168.
3 (1ce2ed4, 3fdf168) code-reviewer Figures and harness proof hold; a re-run after the cache refresh was identical. Three findings. My extra clause made the vote narrower than the rule for a surname spelled as the marker opening the name (Oğlu Ahmad oğlu). The vote is wider in four shapes inherited from master's four-word vote: a suffix comma, a bound given name, a final full stop, a bracketed marker. decisions/O2's suggester bullet was stale. The clause is dropped (row added), and the inherited widths are recorded as a follow-up candidate in decisions/group-suggestion. The bullet now points there.
4 (6a9df3b) independent review (coordinator) The parse change is clean. The three-word vote is wider than the rule in four shapes (a nickname, a bound given name, a suffix comma, a final stop), which the four-word arm already had on master. The docstring overstated the vote. Two comma rows were missing from _TURKIC_THREE. Docstring corrected. The gap is recorded for both arms and pinned in test_suggest. Comma rows added (neither moves). Final-stop fix proposed above. Done in 69e11b9.

🤖 Generated with Claude Code

derek73 and others added 4 commits November 12, 2026 12:33
…s the family (#1187)

Under Turkic handling, a name of exactly three name words ending in a
standalone patronymic marker reads the father's name and the marker as
the family, as #1253's decision states for a Kyrgyz name with no
surname: Бекмырза Чолпонбай уулу under locales.TR_AZ gives family
'Чолпонбай уулу', where it gave 'уулу'. Two words and five keep the
positional reading. The default does not move. suggest_measure's TURKIC
comparator takes the father's name and the marker for such a name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d correct its record

From review: with the East Slavic rule on, O1 could rotate a marker-first
name and the new branch then folded the patronymic into that family; the
branch now requires the marker to be the last name word. rules/O2 gains a
Precedence bullet over O6, its bound-given-name and suffix-comma
boundaries as Accepted bullets, and its Signal line; O6, O7 and
decisions/R9 follow. decisions/O2's figures state their recipes, the
suggester's TURKIC comparator change is described against the recorded
table, and the matching cost and the suggester's narrower vote are
recorded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a marker (#1187)

_suggest._patronymic now votes TURKIC where rules/O2 reads a name: three
name words with the marker last, as well as four. A group of Kyrgyz
names with no surname decides the rule. suggest_measure moves 5 cells,
none in the population rows; the harness proof holds. Adds the test
rows review asked for: one case and decomposed markers, a five-word
name under two_family_names, and the TURKIC comparator's truth.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the round-2 review: the name count is over the names both trees
hold, uz_senate's Cyrillic spellings are aliases, and the release log
says 1.4.0 read the shape with Turkic handling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 added this to the 3.1 milestone Nov 12, 2026
@derek73 derek73 added enhancement non-latin-script Names written in a script other than Latin (rules/W) locale-packs Locale packs and language choices (nameparser.locales) patronymics Father's names and the patronymic view (rules/R9) labels Nov 12, 2026
@derek73 derek73 self-assigned this Nov 12, 2026
…the vote's inherited widths

From the round-3 review: the three-word vote no longer refuses a marker
among the first two words, which the rule reads (Oğlu Ahmad oğlu); the
vote's widths inherited from the four-word vote are recorded in
decisions/group-suggestion, and decisions/O2's suggester bullet points
there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
derek73 and others added 2 commits November 12, 2026 15:40
Both Turkic arms of `_patronymic` count the words `_name_words` keeps,
not rules/O2's name words, so they vote where the rule reads nothing: a
nickname (or a bracketed marker), a given name P5 binds from two words,
a suffix comma and a final full stop. The rule the vote turns on leaves
those names as they were. The docstring no longer says the three-word
vote reads "as the rule reads them"; decisions/group-suggestion's #1187
entry records the four shapes on both arms with their inputs and why the
gap is harmless; tests/v2/test_suggest.py pins them as recorded
behavior, with the four-word nickname name the rule now reads and a
group of five whose suggested rule moves nothing. _TURKIC_THREE gains
the empty-head and full-head family-comma rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73
derek73 merged commit d545ba1 into master Nov 13, 2026
14 checks passed
@derek73
derek73 deleted the feat/issue-1187-father-marker-family branch November 13, 2026 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement locale-packs Locale packs and language choices (nameparser.locales) non-latin-script Names written in a script other than Latin (rules/W) patronymics Father's names and the patronymic view (rules/R9)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should a Kyrgyz name read Father uulu as the family? (Бекмырза Чолпонбай уулу gives family уулу)

1 participant