Skip to content

Report the order on a name of one word followed by initials (#1254) - #1348

Merged
derek73 merged 7 commits into
masterfrom
feat/issue-1254-report-initials-fork
Nov 12, 2026
Merged

derek73 merged 7 commits into
masterfrom
feat/issue-1254-report-initials-fork

Conversation

@derek73

@derek73 derek73 commented Nov 12, 2026 •

Copy link
Copy Markdown
Owner

The third of three PRs implementing the #1254 decision: #1345 and #1347 are merged, and master is merged into this branch, so the diff against master is the report alone.

What it does

Under the given-first order, one name word followed by nothing but initials now reports the fork as an order ambiguity. It names no alternative: the other reading lays out the whole name (the word in front as the family, the letters as given and middle initials), which no one word's other role names. The detail says so in words, with name_order=FAMILY_FIRST, the setting that reads it. The reading itself does not change.

Input Default reading Report
Armitage J. O. given Armitage order
Gomes A.R.S. given Gomes order, suffix-or-name (as before)
Kavitha S given Kavitha order
Lakshmi R S given Lakshmi order

The report is emitted at its decision site, _assign_main's positional layout, under the given-first order. It is inline and nested, so a plain name exits at its second piece. The serial frame band holds.

What counts as initials: letters in rules/T5's shape, spaced, or joined by full stops (A.R.S., measured on the composed spelling so NFD reads alike), ending the name words. A Cyrillic byline reports, spaced or joined (Иванов И. И., Иванов И.И.).

What it does not report (each is pinned by a test):

  • John Smith
  • Zhi LI, Armitage JO: capitals written as one word with no full stops (see the first decision below)
  • Smith, J.O. and , R S: a family comma names the family
  • a declared family-first order (both orders)
  • initials_as_family=True
  • Ram Bahadur B K: a second name word in front
  • J R S, J.A. K.D.: a run of initials in front (rules/T7)
  • Van R S: a particle in front, whose own particle-or-given fork reports it
  • Kavitha s: a lower-case letter among capitals (rules/T4)
  • Dupont J.-P., Smith J-P: hyphenated initials, which carry no initial tag
  • 김 v: a word in a script that writes no initials

Decisions for the maintainer

  1. Bare capitals (Armitage JO) are not reported, though Should Armitage JO read family 'Armitage'? A surname followed by initials, with no comma, reads the initials as the family name #1137 names that very example. Nothing in the parse tells JO from Zhi LI: both are untagged capitals read as the family. On the 3.1 study populations:

    • leaving them out leaves 592 of 2,311 ORCID credit names confirmed as bylines unreported;
    • counting them would also report 92 of the 592 names of Turkey's parliament (Erkan BAŞ) and 276 of a 60,000-name ClinicalTrials.gov sample (Antoine BEDU), all surnames written in capitals.

    This is why the PR says Refs Should Armitage JO read family 'Armitage'? A surname followed by initials, with no comma, reads the initials as the family name #1137 rather than Closes. Keep the choice, or report capitals too and accept the surname reports.

  2. The reserved order kind, not a new one. AmbiguityKind.ORDER has been reserved since 2.0 for "the name's field order itself is uncertain", which this is. A new kind would be new public API; this adds none, but it is the first time order is emitted.

  3. Only one-word heads report, as the decision worded it. Two name words before initials (Rincón Durán S. A., Ram Bahadur B K) do not.

  4. A one-letter numeral read as the family reports both forks. John V, Malcolm X and GND's regnal Heinrich I. (which T5 already reads as an initial) report order beside their suffix-or-name.

  5. 22 case rows gain order; their classifications are unchanged. The classification records how fields compare with 1.4.0, which had no reports, and no field moved. Two rows were renamed from ..._is_silent to ..._reports_no_link.

Measurements

These were taken against a checkout of #1347's head (29e86c7); the committed corpora and the match were re-taken against master (e9c74d2) once it held #1347.

Committed corpora, against master: 63 names gain the report, and only their ambiguities move (the report carries no alternative). That is 61 at the reviewed commit plus two rules/O8 examples #1347's review added (Lakshmi R S V, Ram R S). The rule examples added here are new to the corpus.

Local corpora, with snapshot.py --local <source> --base <that checkout> at this head; only ambiguities moved:

source names gaining the report
orcid-researchers 4,939
nepal-candidates 1,580
tse-donors 1,402
patentsview-inventors 437
ctgov-officials 392
jrc-names 133
psc-individuals 13
fec-individuals, cz-candidates, dof-signatures, govuk-people, tw-donors, uit-vinames, ukec-individuals, vn-assembly 0

opensanctions-parliaments was not read: its cache predates six of the datasets the tool reads.

Hand read:

  • PSC's 13: Nepali K C/B C, South Indian G M, and given names with a family initial (Alyssa X., Camilla P).
  • A seeded sample of 40 of ctgov's: about 28 bylines the default reads wrong (Jabs D, Smith C), about 5 South Indian (Prathik B H), and about 5 given names with middle and family initials (Nancy K M). A reader would hesitate over nearly all of them.

Matching, tools/differential/match_diff.py --base <checkout of master e9c74d23>: 0 of 655,473 rows moved, and no consistent pair shares no key, and no consistent pair shares no key. The report carries no alternative, so the match tries nothing for it and _match.py is unchanged. Whether the match should re-read such a name under the other order is #1303's question, which this report now gives a trigger for (decisions/name-matching says so).

Recorded controls re-taken, each with its reason:

  • the field sweep: 1,860 → 1,882 claims
  • the alternative sweep's skips: unchanged at 366 (the report carries no alternative)
  • the one-case grid's unguarded count: 414 → 507
  • the multi-report grid: 3,744 → 3,780, verified to be all order

Review round 1 (1c30154)

  1. No alternative (the review found every tried reading was a hybrid the parser never produces: Mr. Smith / Smith E.T. matched through family 'Smith E.T.', while Smith J. / John Smith stayed inconsistent). The order report now carries none. A fill loop in _assign was giving it a name reading, so the report is appended after that loop. _check_alternatives asserts None for order. rules/A1, rules/O4, decisions/O4, A1, D2 and name-matching, AmbiguityKind.ORDER's docstring, docs/policy.rst and the release bullet are corrected.
  2. The detail text said "followed only by initials" where a post-nominal follows (PHUOC T DO, Sigve N Aas, PhD, Felicio S Neto). By the rule's own terms a post-nominal is no name word, so these keep the report, and the text now says "the only name word before initials". Rows pin it. The counts are unchanged: ctgov 392 (30 with a suffix after), tse-donors 1,402 (457).
  3. Silences stated as limits, with rows, not extended: Devanagari letters with a vowel sign (राम बि.क., What does an initial look like in Devanagari, Bengali and the scripts like them? (एम. एस. वर्मा gives initials() 'ए. ए. व.') #1273), transliteration digraphs (Ivanov Yu. A.), and a one-case Y (SILVA Y, silva y). rules/P8's sentence now holds only for the marked letters.
  4. rules/O4:
    • The leads say "no order" (a declared given-first order reports, and the given-first order reports default or declared).
    • The rows show each silence (12 S., 王 J) and a hyphenated initial (Dupont J.-P.).
    • New Precedence bullet against a particle in front (Van J. S.). The Signal: line names the shape.
    • decisions/O4 says it narrows After a name with no comma, are initials the family name or the given name's initials? (Armitage JO vs Lakshmi R S) #1254's decision on glued initials, with both costs; it marks the session-notes counts as dated snapshots, and says why opensanctions-parliaments was not read.
    • O4 should become a rule of its own, as O5 did: it reads a word count and a shape, not position. The size test does not ask for it, so it is not split here.
  5. Mutation survivors:
    • NFC on the head and the head's letter test now have rows (NFD É S; ?? S, 12 S., -- J O).
    • Removed as unreachable by construction:
      • the comma and segment tests: _assign_main runs only on segment 0, under no comma or a suffix comma;
      • by_script: a script's order needs a wholly Han, Hangul or kana name, which holds no initial;
      • the head's initial tag: one letter, refused by the chunk test;
      • chunk.isalpha(): the dotted shape tag passes period_joined_vocab's alphabetic gate.
    • A _PREFIXED_SHAPES benchmark row for the per-piece walk. Re-taken on the row's own harness at load average ~5: 4.00–4.05 clean, 7.5 with one list scan planted per piece (failing three runs of three, 1.25x over the 6.0 bound), 12.0–12.1 with two scans. The first figure quoted here (11.47–12.23) was the two-scan plant.

Review round 2 (b4593a0)

  • order is added to the lists of reports that carry no alternative: Ambiguity.alternative's docstring, docs/usage.rst, and nameparser/_pipeline/AGENTS.md's "every emitter names the reading it did not take".
  • The benchmark margin is re-taken (above).

Docs

  • rules/O4: a Then bullet, three Except bullets and an Accepted bullet. The rules/P8 and S10 examples and their bullets now name the order report beside theirs.
  • decisions/O4: a dated entry and a Standing line.
  • decisions/A1: a dated note that order is now emitted.
  • AmbiguityKind.ORDER's docstring, no longer "reserved".
  • docs/policy.rst: one paragraph and a doctest in the initials-as-family section.
  • The release log: one bullet, its "2.0.0 through 3.0.1" range checked on the wheels.

Checks

Refs #1137
Refs #1254

🤖 Generated with Claude Code

derek73 and others added 2 commits November 11, 2026 17:12
…amily (#1254)

The default reading of letters ending a name does not change:
`Lakshmi R S` keeps middle `R`, family `S`. The new opt-in switch
(rules/O8) reads two or more letters in a row, each in the shape rules/T5
reads as an initial, ending the name words under the given-first order,
with no family comma and a name word before them, as the family:
`Lakshmi R S` gives family `R S`, `Ram Bahadur B K` family `B K`. It
stands down under both family-first orders, where a byline written
surname first (`Huntley R P`) already reads right.

locales.NE turns it on through ne.toml's [rules]; Parser.suggest turns
it on for a group where one run of letters ends at least two names and
at least half of the names ending in a run, a spaced run counted where
the rule moves the name (asked of the parse with the switch on and off)
and a run joined with full stops counted where the parse makes it the
family. A group decided so casts no trailing-initial vote on its order.

With the switch off nothing moves: the snapshot changes only by the
rule's new example names, and every local corpus read matches the base.
The decision and its measurements are in decisions/O8 and
decisions/group-suggestion's 2026-11-11 LETTER RUNS entry.

Closes #1163
Refs #1254

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`Armitage J. O.`, `Gomes A.R.S.`, `Kavitha S` and `Lakshmi R S` read
the word in front as the given name by the default given-first order;
a bibliography writes it as the family name, and a South Asian list
writes the letters as the family (rules/O8). The default stays, so the
fork is reported, in the `order` kind reserved since 2.0, at assign's
positional layout, its alternative the word in front as the family.

Not reported: a declared family-first order, a family comma, the
initials_as_family switch, a second name word in front, a word in front
that is itself a run of initials, a particle (its own fork reports it)
or a word in a script that writes none, and capitals written as one
word with no full stops (`Armitage JO`), which are written as a short
surname is (`Zhi LI`).

61 names of the committed corpora gain the report, and only their
reports move; in the local corpora, orcid-researchers 4,939,
nepal-candidates 1,580, tse-donors 1,402, patentsview-inventors 437,
ctgov-officials 392, jrc-names 133, psc-individuals 13, the eight
others none. rules/O4 and decisions/O4 carry it.

Refs #1137
Refs #1254

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 name-order Name order, family-first and two family names (rules/O) initials Reading initials and the initials() view (rules/T) labels Nov 12, 2026
@derek73 derek73 self-assigned this Nov 12, 2026
derek73 and others added 5 commits November 11, 2026 19:06
NE's DEVIATES and the suggester's pre-test now share one predicate that
divides words at every non-letter, so a bracket, a glued comma or a
zero-width character no longer hides a name the rule moves. The
suggester no longer counts hyphenated runs and suggests nothing under a
base where the switch changes no name (family-first, middle_as_family).
O8's unreachable family-comma and order guards are removed; its other
guards and the O7 precedence get rows. rules/O8 states the particle,
numeral, dotted-credential and Devanagari limits; decisions/O8 and
group-suggestion reconcile their counts, with the stricter suggestion
rules measured and declined.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The order report names no alternative: the other reading lays out the
whole name, which no one word's role names, so a tried single-word
reading was a hybrid the parser never produces. Its detail says the
other reading in words, with name_order=FAMILY_FIRST; the name match
tries nothing for it, #1303 owning a re-read. The detail no longer
claims nothing follows the initials, where a post-nominal does. The
emitter's unreachable comma, segment, script and initial checks are
removed, the reachable ones get rows, and the per-piece walk gets a
benchmark row. rules/O4 and P8 state the silences (Devanagari vowel
signs, digraphs, one-case Y, hyphens, a particle in front).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ambiguity.alternative's docstring, docs/usage.rst and the pipeline
AGENTS.md now list `order` beside the shape reports and the opening
connective. The benchmark row's measurement is re-taken on its own
harness: one planted list scan reads 7.5x, 1.25x over the bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The branch carried #1347's commits before it was squash-merged, so the
merge is built as master plus this PR's own changes (b4593a0 against
the #1347 head it had merged, 29e86c7), which apply to master
cleanly; the rules corpus and the snapshot are regenerated. Against
master the snapshot moves only by 63 names gaining the order report
and 15 example names new to the corpus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73
derek73 merged commit 58da7b8 into master Nov 12, 2026
14 checks passed
@derek73
derek73 deleted the feat/issue-1254-report-initials-fork branch November 12, 2026 05:35
derek73 added a commit that referenced this pull request Nov 12, 2026
The row arrived from master written against the wall-clock helpers; as a
_PREFIXED_SHAPES entry it already measures through _ratio under @serial.
Its one-scan plant fails it on CPU time, quiet and beside 24 busy loops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
derek73 added a commit that referenced this pull request Nov 12, 2026
…parallel (#1352)

* Time the benchmark's scaling rows on CPU time, and run its counts in parallel

The clock-timed rows in tests/v2/test_benchmark.py read
time.perf_counter(), which counts the time a loaded machine spends
running other processes: under 24 busy loops on 12 cores 19-23 of the
module's 62 tests failed in each of five runs, at up to 10.0x against
a 6.0 bound. They now read the thread's CPU time, interleave the two
inputs, and take more rounds only where the first ones read over the
bound, so no threshold or baseline number moves; the thousand-names
bound stays 5s, now of CPU time.

The frame, call and shift counts lose the serial mark and run in the
parallel suite, so a plain `uv run pytest` holds the band; only the
four timed tests stay in the -n0 -m serial pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Record the benchmark's CPU clock in decisions/parse-cost (#1352)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Judge the timed ratio once, near the bound too; correct the measured claims

#1352's review found two ways a loaded run could pass a real quadratic:
more rounds were taken only at or over the bound, so a ratio that load
DEFLATED (a planted 6.7x read 5.93x once at 24 busy loops) was never
corrected, and the escalated loop stopped at its first reading under
the bound. `_ratio` now takes all 35 rounds wherever its first 7 read
within 20% of the bound or over it, and judges the last minimums;
test_ratio_takes_more_rounds_only_near_the_bound holds that on a
scripted clock and fails against both earlier loops. The weakest
planted quadratic now fails every row in five loaded runs.

Also corrects the review's wording findings: the counted guards include
exact pins up to == 6, "read the same" was "passed", the extra rounds
are not a retry, the 0.05x agreement was 0.35x, 21,093 was 21,065, and
the wall-clock tables before 2026-11-11 are labelled as such.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Test the near line clear of float drift; say the ratio converges, not monotonically

The fix commit's review: the 4.8 boundary row passed only because the
fake clock's float sums landed a ulp over 6.0 * 0.8; 4.7 and 4.9 sit
clear of it. And a ratio of two falling minimums is not monotone, which
is why _ratio judges it once at the end -- the prose said otherwise.
AGENTS.md's 21,093 becomes the population the decisions entry names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Read #1348's order-report row on the CPU clock too

The row arrived from master written against the wall-clock helpers; as a
_PREFIXED_SHAPES entry it already measures through _ratio under @serial.
Its one-scan plant fails it on CPU time, quiet and beside 24 busy loops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement initials Reading initials and the initials() view (rules/T) name-order Name order, family-first and two family names (rules/O)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant