Skip to content

Word a report's field from the word's final role (#626) - #628

Open
derek73 wants to merge 5 commits into
masterfrom
fix/issue-626-report-final-field
Open

derek73 wants to merge 5 commits into
masterfrom
fix/issue-626-report-final-field

Conversation

@derek73

@derek73 derek73 commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

Some ambiguity reports name the field their word was read into ("read as a given name"). Six of assign's reports took that field from the word's role at assign, but rules in post_rules can still move the word:

  • H1 moves the name behind a title into the family.
  • P1's family-first fold lays the rest of the name out by the order.
  • P6 attaches a trailing name word to the family at the end of a name read family-first.
  • Under opt-in policies, the patronymic rotations (O1, O2) and middle_as_family's fold (O3) move one too.

So the report could name a field the word doesn't end up in:

Input Policy Lands in Report said
Attorney General of Minnesota default family "read as a given name by convention" (since 2.3.0)
Kim Min Do FAMILY_FIRST family "read as a middle name" (this cycle, after #289)
de Kim Ma FAMILY_FIRST given "read as a middle name" (this cycle, after #289)
, Ma Dr. default family "read as the given name" (this cycle, after #289)
Van Ivan Petrovich East Slavic patronymic rule family "read as a given name" (since 2.3.0)

The report is still created where the parse makes its choice. Only the field word moves to assemble, the one place that knows final roles:

  • An emitter that names a field writes its sentence up to the field, and passes the rest as PendingAmbiguity.field_tail. An empty string means the field ends the sentence.
  • assemble joins the two halves around FIELD_READING for the first token's final role.
  • The six emitters are H4's all-suffix name, title-or-name's join clause, O5's lone word, the trailing peel's picks, the leading ambiguous particle, and the report on the word right after a comma.
  • A field report in a name emptied of content is dropped, rather than shipping half a sentence. No report reaches that case today.
  • An import-time check confirms FIELD_READING covers every role.

One user-visible wording change beyond the field itself: the comma report's given-side text changes from "read as the given name" to "read as a given name", matching the other reports.

Measured (recipe in decisions.md#A1)

  • Generated grid (53,517 texts, including commas with nothing before them and a trailing title, under all three orders; the opt-in movers are outside it): on master, 2,725 of 89,092 field claims named the wrong field. They came from three emitters: title-or-name's join clause (1,575), the trailing peel's picks (1,114) and the comma report (36). On this branch: 0.
  • Fingerprint against master (differential corpora, case-table names and a comma grid, 13,090 names under six policies): no role, report kind, initials or rendering moves. The details that change:
    • 6,395 comma reports on 1,086 names: "the given name" becomes "a given name".
    • 85 comma reports on 15 names now name the family.
    • 40 title-or-name reports on 10 names now name the family.
  • Opt-in policies: a review grid of 12,593 texts under 16 configurations (patronymic rules, middle_as_family, suffix delimiters, the caps and dotted switches, the RU, TR_AZ, ZH and JA locales) found 0 wrong claims on this branch, against 26 to 512 per configuration on master.
  • Five differential gates: all exit 0. The reference frame-count pins are unchanged; names that carry a report are 2 frames cheaper than on master.

Tests

  • test_a_report_names_the_field_its_word_lands_in (tests/v2/test_cases.py): every non-locale case row under all three orders. Rows that carry their own policy are checked under that policy only.
  • test_the_field_sweep_sees_the_claims_it_checks: records how many claims the sweep checks (1155), so it cannot pass by checking nothing.
  • New case rows, each label from git bisect against the wheels' readings:
    • Attorney General of Minnesota (parity, checked against the 1.4.0 wheel)
    • Kim Min Do (fix(#289))
    • de Kim Ma under FAMILY_FIRST (fix(#289), core-only)
    • , Ma Dr. (fix(#316))
    • Van Ivan Petrovich (East Slavic) and Van Ali Veli oglu (Turkic), both parity
    • Do Bishop Do under FAMILY_FIRST with middle_as_family (fix(#289), core-only)
  • Unit tests for assemble's join, its handling of an emptied name, and which token's field it names. test_assign.py now reads details from the final parse, through run().

Docs

  • rules.md#A1: new statement clause; interacts now lists H1, O1, O2, O3, P1 and P6.
  • decisions.md#A1: new 2026-10-08 entry, including what the first draft and its reviews missed, an exact recipe for recomputing the numbers, and an Open: #629 line.
  • mechanisms.md: AMBIGUITY-AT-THE-DECISION-SITE contract, with the Smith, Jr., Dr. Bart reports its last part as "consumed as suffix" when 'Dr.' is read as a title #629 exception noted.
  • AGENTS.md: the decision-site bullet, plus a sweep-paragraph lesson that empty-head comma grids need a trailing title.
  • Release log: one bullet, covering the two shipped cases (Attorney General of Minnesota and the patronymic Van).

Review

Three review rounds and a /simplify pass:

A related report outside #626's class (segment's "consumed as suffix best-effort" after #603) is filed as #629.

Closes #626

🤖 Generated with Claude Code

Five of assign's reports named the field their word was read into
from the role it held at assign, and two later rules still move a
word: H1 takes a lone unit behind a title into the family, and P6's
attachment takes a trailing name word into the family at the end of
a name read family-first. So `Attorney General of Minnesota` said
'General of Minnesota' was "read as a given name" (since 2.3.0), and
`Kim Min Do` under FAMILY_FIRST said 'Do' was "read as a middle
name", each with the word in the family.

The decision stays at its site; the field's wording moves to
assemble, which alone knows final roles. An emitter naming a field
writes its sentence up to the field and passes the rest as
PendingAmbiguity.field_tail; assemble joins them around FIELD_READING
of the first referent's final role. All five emitters use it.

Measured on master over 51,835 names under all three orders: 2,689 of
66,208 field claims named the wrong field; on the tree, 0. No role,
kind, initials or rendering moves on the fingerprint; 40 details
change, all title-or-name 'given' -> 'family'. Guarded by
test_a_report_names_the_field_its_word_lands_in over every case row
under all three orders (control: 10 failures on master).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 added the bug label Oct 9, 2026
@derek73 derek73 self-assigned this Oct 9, 2026
@codecov

codecov Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.01%. Comparing base (26cdb89) to head (aa48ff5).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #628   +/-   ##
=======================================
  Coverage   99.01%   99.01%           
=======================================
  Files          46       46           
  Lines        4481     4486    +5     
=======================================
+ Hits         4437     4442    +5     
  Misses         44       44           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

derek73 and others added 4 commits October 8, 2026 20:23
The comma report on the word after a family comma hardcoded "read as
the given name", and with nothing before the comma H1 moves that word
to the family behind a trailing title (`, Ma Dr.`). It now defers its
field to assemble like the other five, so its given-side wording reads
"a given name". P1's family-first fold is a third rule moving reported
words (`de Kim Ma` under FAMILY_FIRST); the comments and docs that
named only H1 and P6 now name all three, and "H1's swap" is H1's move.

Assemble withdraws a field_tail report in an emptied name instead of
shipping half a sentence, and FIELD_READING is asserted complete over
Role. The sweep's phrase list covers the settled phrasings too (the
suffix run's, the numeral fork's, H4's "the name", P6's), states that
locale rows are not checked, and a second test records how many claims
it checks (1151) so it cannot go vacuous. Rows `, Ma Dr.` (fix(#316))
and `de Kim Ma` under FAMILY_FIRST (fix(#289)), both bisected; the
`Kim Min Do` note no longer claims both family-first orders. Unit
tests for assemble's join; two test_assign names now say "field".

decisions.md's entry carries a recompute recipe and re-measured
figures: 2,725 of 89,092 claims wrong on master over 53,517 texts
(comma shapes with an empty head and a trailing title added), 0 on
the tree; control 11 failures on master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The patronymic rotations (O1, O2) and middle_as_family's fold (O3) also
move a word assign reported, under opt-in policies no three-order grid
reaches, so reverting the leading-particle emitter passed the whole
suite. Rows `Van Ivan Petrovich` (East Slavic), `Van Ali Veli oglu`
(Turkic) and `Do Bishop Do` (FAMILY_FIRST + middle_as_family) pin them,
and every mover list now names them. The sweep's claim count moves
1151 -> 1155 with the rows, its control on master 11 -> 14, and the
sweep reads its population from `_swept_rows` rather than a copy of
the skip.

decisions.md#A1 gains `Open: #629` (segment's "consumed as suffix"),
which mechanisms.md and the release log now qualify; AGENTS.md says the
guard covers only the phrasings it lists. The `, Ma Dr.` report dates
from #289, not #316; the recipe names the 6f15f21 case table and the
collapsed empty-head space, and scopes its figures to the three orders.
A mixed-role unit test pins assemble's first-referent choice; the
2026-09-17 entry notes the rewording; the release bullet adds the
patronymic example, which 2.3.0 also misreported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The recipe's case table is 0c54662's, the parent of #614's first
commit (6f15f21 has the same table but is not that parent), and the
claim that today's table moves the wrong count by at most two was
false: the rows the reviews added read 6 more on master. The random
draws, the stripping and the comma forms are now stated exactly
enough to rebuild the 53,517 texts. rules.md#A1's interacts list names
the movers the entry names: P1 and O1 to O3 beside H1 and P6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The two order-sweep invariants walk one `_SWEPT_ROWS` list, so the
row filter is stated once and neither test skips (582 -> 110 skips
in the suite); `_NAME_FIELDS` is `NAME_ROLES`; test_assign's
`_reported` reads through `run` rather than a hand-listed stage chain.
In assign, title-or-name's two branches share one constructor, the
particle emitter's comment points at `PendingAmbiguity.field_tail`
for the movers instead of carrying a third copy of the list, and its
one-use `token` binding is inlined. No behavior change: fingerprint
byte-identical on every common name, field grid 0 of 89,092, five
gates exit 0.

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

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Kim Min Do under FAMILY_FIRST is told 'Do' was "read as a middle name" when it lands in the family

1 participant