Skip to content

Read a nickname, one name word and a suffix as the family name (#815) - #1107

Merged
derek73 merged 5 commits into
masterfrom
fix/issue-815-n3-suffix-aside
Nov 6, 2026
Merged

derek73 merged 5 commits into
masterfrom
fix/issue-815-n3-suffix-aside

Conversation

@derek73

@derek73 derek73 commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

Closes #815

N3 (the lone-word nickname rule) now sets a suffix aside, as H1 (a title and one name word) and M4 (a maiden marker makes the lone name word the family) already do. A nickname, one name word and a suffix read the word as the family name and no longer report given-or-family:

'Smitty' Jones Jr.    2.0.0–2.8.2: given 'Jones', family ''  (+ given-or-family since 2.3.0)
                      now:         family 'Jones', suffix 'Jr.'
Jones (Smitty) PhD    same move

This is option A from the issue, chosen with the Nepal cost below accepted.

How

N3's early count in _assign_main (one piece in the segment) is unchanged. The suffixed shape is decided at O5's given-or-family site, after the trailing peel has set the suffix aside and after O5's own clauses (no title, maiden name or script order; the word not an initial, bound given name or particle) have said nothing else decided it. A nickname there takes the family and the report goes. The scan is gated on state.extracted, so a name with no delimited clause pays no frame: Madonna, Smith Jr. and the reference name keep master's call counts, and the moved names get cheaper ('Smitty' Jones Jr. 233 → 217).

Reach, each pinned by a case row:

  • A nickname in any part of the name: Jones Jr., 'Smitty' → family. The early count reads the nickname this way too.
  • An S1 credential clause: Jones (PhD) Jr. → family. The clause still carries the nickname role at assign, and the bare Jones (PhD) already read family.
  • Words outside O5's claim list: a given name written short ('Smitty' Chas. Jr.) and a period-shaped word ('Smitty' Xyz. Jr.) → family.
  • An ambiguous acronym in capitals: 'Smitty' Jones ING → family, because S4 reads it as the suffix.

Not reached, by design:

  • Read as a second name word: a one-letter numeral (V, S10), the gated words fils, Junior and KC (S11), and a Title case acronym (Ing, S4).
  • A title word as the one word: 'Smitty' Pope Jr. keeps H4's title-or-name (new N3 Precedence bullet).
  • A nickname alone before a comma, or an empty head: 'Smitty', Jones Jr. and , 'Smitty' Jones Jr. stay given.
  • Claimed words beside a suffix: 'Smitty' J. Jr. stays given (N3's Except), while bare 'Smitty' J. reads family. That inconsistency predates this PR and is recorded in Accepted rather than widened.

Under the family-first orders the field was the family already; only the report goes.

Measured moves (2026-11-05, comparator: master 90a9a86)

Source Moves Names that could move*
committed corpora (test_snapshot.py) 1: 'Smitty' Jones Jr. —
cldr_agreement.py, every view 0 —
fec-individuals (--base) 0 10 of 1,893,964
ctgov-officials 0 6 of 352,104
govuk-people 0 1 of 6,021
ukec-individuals, tse-donors, dof-signatures 0 0
psc-individuals agreement (--base) matches the base —
nepal-candidates 3, all worse, accepted 3

* Names that parse with a nickname, a suffix, no middle name and exactly one of given and family.

The Nepal three each have a surname the suffix vocabulary also lists (Od, D.C, जी.सी.) beside a clan name in brackets that was read as a nickname: Rewati Od (Mahar), Sumnime D.C(Oli), गोपाल जी.सी.(घर्ती क्षेत्री). The given name went from given with a report to family with none.

The snapshot.jsonl diff holds the one move plus new rule-example and shape-inventory entries.

Docs (same-PR amendment)

Tests and negative controls

  • test_parser.py suffix grid: 440 rows (5 nickname spellings × 4 word spellings × 11 suffixes × the default and FAMILY_FIRST orders). FAMILY_FIRST_GIVEN_LAST reads every row as FAMILY_FIRST does, by roles, tags and reports. It compares as_dict() whole and takes 0.05s.
    • Control: all 440 rows fail on master 90a9a86; none fail on the branch.
  • Claimed-word test: 5 rows. Control: moving the nickname test ahead of the claim clause flips all 5 to family.
  • cases.py: 18 new rows, and the existing row renamed and flipped. The field-sweep count goes from 1647 to 1662.
  • Runs: uv run pytest, -n0 -m serial (the frame band holds), mypy, ruff, and Python 3.15 in its own environment all pass.

Reviews

Round 1, on fc83ff2:

  • pr-review-toolkit:code-reviewer: no code defect. Fixed the release-log range (2.8.0 → 2.8.2, the report since 2.3.0) and gated the scan on state.extracted, which removes the frames it found on lone words with no nickname.
  • pr-review-toolkit:pr-test-analyzer: fixed.
    • Added rows for the title word (H4 Precedence), caps vs Title case acronyms, gated words, VI and Ph. D., a quoted nickname after the word, the comma reach, the period shape and the given abbreviation.
    • Corrected the grid comment that said the caps acronyms don't move.
  • pr-review-toolkit:comment-analyzer: fixed the release-log range and the limit sentence, the cross-segment reach, the stale comment wraps and the case-note version range.
  • design-docs-reviewer: fixed.
  • /simplify (reuse, simplification, efficiency, altitude):
    • Applied: parse each bare name once; drop the order that reads identically; compare as_dict() whole; remove the tautological control test; state the N3 handoff once; collapse the count history.
    • Altitude: no finding. Merging the two N3 sites would move readings and cost 25 frames on 'Smitty' Jones.
    • Skipped: dropping grid-duplicated case rows, which would move the snapshot.

Round 2, on the fix commits 430e59d and 50b1736:

  • code-reviewer: the gate is reading-neutral. It was fuzzed with asserts over 6,811 corpus names under seven parsers plus 60,000 random strings, and dropping FFGL loses nothing. Fixed three rows mislabelled parity: 'Smitty' J. Jr. → fix(suffix-routing), 'Smitty' Jones, Jr. → fix(Should parse("Smith, Jr.") put "Jr." in title rather than suffix? #296), 'Smitty' Pope Jr. → feat(An input composed entirely of titles should report an ambiguity — "The Right Hon. the President of the Queen's Bench Division" #491).
  • pr-test-analyzer: both controls hold. Fixed the Xyz. mechanism (case note and decisions entry), the grid parse count (480) and the missing empty-head row.
  • design-docs-reviewer: fixed.
    • The Nepal suffixes are vocabulary readings, not dotted-shape ones.
    • N3's Except lead now lists exactly its three readings.
    • O5's M4 exception no longer contradicts M4 on particles.
      Round 3, on the round-2 fix commit 1991581:
  • design-docs-reviewer: three prose and label errors, no reading errors; all fixed in the last commit.
  • Follow-up noted, not fixed here: rules/M4's own Except says "a word the vocabulary has claimed as a given name", which is wider than its code (bound given names only). The wording predates this PR; it is M4's to fix.

🤖 Generated with Claude Code

N3 (the lone-word nickname rule) now sets a suffix aside, as H1 (a
title and one name word) and M4 (a maiden marker makes the lone name
word the family) already did: "'Smitty' Jones Jr." reads family
'Jones' and no longer reports given-or-family. The early count is
unchanged; the suffixed shape is decided at O5's site, after the
trailing peel, so a word the vocabulary or its shape claimed keeps its
claim ("'Smitty' J. Jr." stays given 'J.').

Rules N3, O5 and M4 amended; decisions/N3 records the measurement
(one committed-corpus name, three nepal-candidates names taken as the
cost) and closes the question decisions/H1's #410 entry left open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 added this to the 3.0 milestone Nov 6, 2026
@derek73 derek73 self-assigned this Nov 6, 2026
derek73 and others added 4 commits November 5, 2026 19:50
- Gate the nickname scan on state.extracted, so a lone word with no
  delimited clause pays no frame (Madonna and Smith Jr. back to
  master's call counts).
- rules/N3: the Except cites the rules whose reading a word keeps (T5,
  T4, P5, P4) and no longer claims M4 agrees on particles; a Precedence
  bullet gives a title word to H4; Accepted covers the dotted Nepal
  shape and the comma reach (a nickname in any part, an S1 clause, a
  nickname alone before a comma).
- decisions/N3: capitalized headline, the 660-row grid, the reach the
  reviews found, and the population bounding each local-corpus zero;
  decisions/H1's #410 head marked.
- Tests: the grid walks 660 rows in one test (quoted nicknames after
  the word, VI, Ph. D.), the claimed-word test adds bare and one-case
  initials and a particle, and case rows pin the comma, S1, acronym,
  gated-word, title-word, period-shape and given-abbreviation shapes.
- shapes.py: a nickname-and-suffix arrangement under each order.
- Release log: 2.0.0 through 2.8.2, the report since 2.3.0, and the
  full Except.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The suffix grid parses each bare name once and drops
  FAMILY_FIRST_GIVEN_LAST, which reads every row as FAMILY_FIRST does
  (440 rows, all failing on master 90a9a86); it compares as_dict()
  whole, so a title or maiden name moving fails it too.
- The claimed-word control stays as data in its comment; the test that
  only asserted a length is gone.
- _assign.py: the N3 handoff is stated once, at the decision site.
- test_cases.py: one dated step for #815's claim count.

snapshot.jsonl unchanged; frame counts unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- rules/N3: the Except lists exactly the three readings it keeps and
  says a given name written short is none of them; the Nepal Accepted
  bullet is the vocabulary reading again (D.C and जी.सी. are listed
  credentials, not dotted-shape reads), and decisions/N3 says so.
- rules/O5: M4's exception names the given-name and initial claims
  only, since M4 flips a particle (de née Jones -> family 'de').
- cases.py: an empty-head boundary row; the Xyz. note states the
  mechanism the parser shows (bare it is taken whole as a title, beside
  a suffix the peel leaves it as the name word); three rows labelled
  parity get the change that moved them from 1.4.0 (suffix-routing,
  #296, #491).
- test_parser.py: the grid's parse count is 480.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- decisions/N3: जी.सी. is listed nowhere; it reads as a suffix because
  its chunk जी is a hi/mr honorific that period_joined_vocab takes as
  a suffix chunk (removing that honorific leaves it family).
- rules/N3: the Nepal Accepted bullet covers a suffix read whole or by
  a period-joined chunk.
- rules/O5: M4 keeps a bound given name and an initial; a given name
  written short (Chas. née Jones) is flipped like any other.
- cases.py: 'Smitty' Pope Jr. moved from 1.4.0 with #489's title-peel
  floor, as its sibling Dr Jr is labelled; #491 added only the report.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73
derek73 merged commit 5c3c0db into master Nov 6, 2026
13 checks passed
@derek73
derek73 deleted the fix/issue-815-n3-suffix-aside branch November 6, 2026 04:16
derek73 added a commit that referenced this pull request Nov 6, 2026
* rules/M4: name the bound-given carve-out for what it reads

M4's Except said "a word the vocabulary has claimed as a given name
keeps that reading", but the guard reads only the vocab:bound-given
and initial tags. Words with a plain `given` reading, which arrived
after #445 (#752's phase 2i, #789), are flipped: `Chas. née Jones` ->
family 'Chas.'. The words now say a bound given name, with that name
as a boundary example; the two code comments quoting or paraphrasing
the old words follow, and decisions/M4 records it. No reading moves.

Found by the third review round of #815 (PR #1107).

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

* rules/M4: state the flip of a plain given reading as a cost

Following the design-docs review of the narrowing: M4's Except gives
its reason as not overruling what a word already IS, so the flip of a
word the vocabulary reads only as possibly a given name is now an
Accepted bullet (Chas. née Jones, Van née Jones -> family) with its
ground, the marker naming the surname, as a title does under H1. The
Except drops "which is nobody's family name", false under both
family-first orders. decisions/M4's entry corrects its history: the
flip dates from #445's own commit (ambiguous particles), not from
2026-10-26, and records widening the carve-out as declined.

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

* Address the fix-commit review of rules/M4's narrowing

- decisions/M4: name every PR that added given readings, #883 among
  them (the conversion that gave van its reading); the declined
  widening now carries its measurement (one corpus name moves, the
  entry's own example), and the H1 analogy is stated as support only,
  since H1 also flips an initial (Dr. J. -> family 'J.').
- rules/M4: the Accepted bullet rests on the marker alone, without the
  H1 analogy.
- mechanisms.md#TWO-LAYER-ASSIGN: a claim is a word's role; a given
  reading is a lean the field rules read past.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should 'Smitty' Jones Jr. read family 'Jones', as 'Smitty' Jones does? (N3 counts a suffix; H1 and M4 set it aside)

1 participant