Skip to content

Add "abd" to BOUND_GIVEN_NAMES, and let a word in two vocabularies satisfy the join reserve - #400

Merged
derek73 merged 1 commit into
masterfrom
fix/abd-bound-given-name
Aug 19, 2026
Merged

Add "abd" to BOUND_GIVEN_NAMES, and let a word in two vocabularies satisfy the join reserve#400
derek73 merged 1 commit into
masterfrom
fix/abd-bound-given-name

Conversation

@derek73

@derek73 derek73 commented Aug 18, 2026

Copy link
Copy Markdown
Owner

abd Allah Smith read given abd, middle Allah, where abdul Rahman Smith reads given abdul Rahman. The spellings that write the article as its own word — Abd Allah, Abd al-Rahman — match none of abdul/abdel/abdal, and the Arabic-script عبد has covered the same word since #269, so only the Latin side was short.

abd Allah Smith          ->  given='abd Allah'   family='Smith'      (was given='abd', middle='Allah')
Smith, abd Allah         ->  given='abd Allah'   family='Smith'
abd Rahman Ahmed Salem   ->  given='abd Rahman'  middle='Ahmed'      (pairwise, like abdul)

Why the wordlist alone doesn't do it

abd is also the postnominal ABD ("All But Dissertation") in SUFFIX_ACRONYMS. The join's reserve counted every piece except titles and suffixes — so the bound word's own piece didn't count toward the three it needed, and the rule declined silently on the common three-word shape. Adding the word and stopping there changes nothing:

                                  abd Allah Smith        Jane Smith, ABD
wordlist only                     unchanged (broken)     suffix='ABD'
+ move to acronyms-ambiguous      given='abd Allah'      given='ABD'  <- credential lost
+ drop from SUFFIX_ACRONYMS       given='abd Allah'      family='ABD' <- credential lost
+ fix the reserve count           given='abd Allah'      suffix='ABD'

The last row is this PR. The claimed piece now counts, which is what the reserve means: it asks whether enough other words are left to spare, and the piece the rule has already claimed as a name is not one of them to spare. Both readings survive — position tells them apart, so Jane Smith ABD, Jane Smith, ABD and Jane Smith A.B.D. all still read the credential as a suffix.

Same shape as #397

Dual set membership shrinking a count that gates a rule is exactly the Catalan i finding — there it shrinks the rootname count P3's single-letter carve-out tests. Second instance in two days. The general question (should membership in one set suppress a word from a count gating a rule keyed on another?) stays open on #397; this PR fixes only the instance in front of it, where the count was wrong on its own terms.

Verification

abd is the only shipped word in both sets — measured, not assumed — so nothing else can move. All 751 differential corpus names are byte-identical and the harness reports 0 unexplained at the 1.4.0 baseline. The corpus contains no abd name, so that is a blast-radius check, not evidence for the fix; the evidence is the tests.

Mutation-verified: reverting the count line alone puts abd Allah Smith back to given abd. The stage-level test in test_group.py uses a synthetic word in both vocabularies, so it pins the mechanism rather than the wordlist, and asserts the reserve still declines at two name words.

3522 tests pass, mypy clean. Per-word evidence comments added on both sides of the collision, in the #: style, so a future editor of either set sees the other.

Review round

Four reviewers ran against this branch. The code review could not break the change and proved the blast-radius claim rather than sampling it: the join's own guard requires a one-token piece, and a one-token piece can never carry a suffix ptag, so dual membership collapses to exactly the set intersection — {abd}. Spellings cannot sneak in either, since A.B.D. normalizes to a.b.d for the acronym test and never matches the bound word. Empirically: 0 diffs over the shipped corpora, and 0 over 124,535 constructed abd-free inputs across all three name orders.

What the reviews changed here:

  • An assertion in the stage test was inertdual Allah never reaches the reserve, an outer >= 3 gate short-circuiting first, so it passed even with the reserve broken. Replaced with dual Allah jr, which the tempting simpler repair (count every non-title piece) fails by joining and leaving no family name.
  • The changed line is a suffix count and nothing combined a firing join with a suffix. Six such shapes reverted silently under mutation; they are now pinned, along with abd Allah Smith ABD — both readings in one string, which is the collision's whole thesis.
  • Two comment claims were false: "Abd Allah" and "Abd al-Rahman" are two-word and do not change at all, and the stated rationale ("spellings that write the article as its own word") names the one spelling still not joined — abd al rahman smith, where al chains forward. That half of the original exclusion survives and is now recorded as a known limit.
  • "Position tells them apart" was too strong: in the given slot of a family-comma name the credential still wins (Smith, Abdsuffix='Abd', no given name, no ambiguity emitted), where Smith, Abdul gives the given name.
  • decisions.md still listed abd under Excluded seven lines below the entry adding it; the constant's own docstring stated the reserve rule this PR falsifies; عبد shipped in 2.0, not 2.1; and the suffixes.py comment named عبد as the dual member when it is abd.
  • This is not a C-ii collision. C-ii settles a precedence by frequency where neither reading is a name. Here one reading is a name and both survive, decided by position — which is C-i's positional qualifier, the de row of that table rather than the vd row. Relabelled, because C-ii is cited elsewhere for a real precedence and the two must stay distinguishable.
  • rules.md#P5 now states its reserve and its S2 precedence, the way P6 already does for the identical situation. P5 previously had no interacts: line at all.
  • The release-log claim is reframed: 0 of 751 corpus names carry a dual-membership word, so byte-identity there tests the corpus. The real argument is arithmetic — for a non-suffix first piece the new expression reduces to the old one.

A pre-existing bug found in passing is filed as #401 (abdul Smith V loses the family name; the reserve counts an initial-shaped Roman numeral as a name word to spare). Not addressed here — it predates this PR and reproduces on master with abdul.

mechanisms.md gains one field note from the review method itself: re-exec'ing a module in-process rebinds its enums to new classes, so is comparisons against the original module's members answer wrong silently — that produced 3,150 phantom movers in one sweep before it was caught.

3531 tests pass, mypy clean, differential 0 unexplained.

🤖 Generated with Claude Code

@derek73 derek73 self-assigned this Aug 18, 2026
@derek73
derek73 force-pushed the fix/abd-bound-given-name branch from fce7dd3 to e862284 Compare August 18, 2026 10:18
@derek73 derek73 added this to the v2.2 milestone Aug 18, 2026
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.53%. Comparing base (55a7822) to head (268b47e).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #400   +/-   ##
=======================================
  Coverage   98.53%   98.53%           
=======================================
  Files          44       44           
  Lines        2942     2942           
=======================================
  Hits         2899     2899           
  Misses         43       43           

☔ 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.

"abd Allah Smith" read given 'abd', middle 'Allah' where "abdul Rahman
Smith" reads given 'abdul Rahman'. The spellings that write the
article as its own word -- Abd Allah, Abd al-Rahman -- match none of
abdul/abdel/abdal, and the Arabic-script عبد has covered the same word
since #269, so only the Latin side was short.

Adding the word alone does not fix it, which is why this is not a
one-line change. `abd` is also the postnominal ABD ("All But
Dissertation") in SUFFIX_ACRONYMS, and the join's reserve counted
every piece except titles and suffixes -- so the bound word's own
piece did not count toward the three it needed, and the rule declined
silently on the common three-word shape. The claimed piece now counts,
which is what the reserve means: it asks whether enough OTHER words
are left to spare, and this piece is not one of them to spare.

Measured, the vocabulary-only alternatives each cost something this
does not: moving `abd` to SUFFIX_ACRONYMS_AMBIGUOUS loses
"Jane Smith, ABD", and dropping it from SUFFIX_ACRONYMS loses the
postnominal outright. Keeping both readings costs nothing here --
position tells them apart, and all three credential spellings still
parse.

`abd` is the only shipped word in both sets (asserted by measurement,
not assumption), so nothing else moves; all 751 differential corpus
names are byte-identical and the harness reports 0 unexplained.

Same shape as #397, where dual membership shrinks the rootname count
P3's carve-out tests -- recorded at decisions.md#P5, with the general
question left open on that issue.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@derek73
derek73 force-pushed the fix/abd-bound-given-name branch from 0b11278 to 268b47e Compare August 19, 2026 02:15
@derek73
derek73 merged commit 5b1d8b6 into master Aug 19, 2026
11 checks passed
@derek73
derek73 deleted the fix/abd-bound-given-name branch August 19, 2026 02:20
derek73 added a commit that referenced this pull request Aug 19, 2026
Price every candidate fix before choosing one, by simulating each
in-process rather than implementing it. Recorded because the practice
paid twice and its absence cost once, all in one session.

#397 and #400 both turned on it: the obvious fix in #400 -- add the
word to the list -- provably changed nothing on the common shape, and
the two vocabulary alternatives each lost a credential spelling. The
winner was a fifth option the wordlist framing had hidden, and none of
that was visible until the candidates ran side by side.

The counterexample is #403's ledger `fields`, widened on one
reviewer's finding without pricing what else the widening claimed. It
took {family, suffix} from a neighbouring rule and two more shapes
from UNEXPLAINED -- diffs in which the rule's own subject does not
move -- and had to be reverted.

Filed here rather than in AGENTS.md because AGENTS.md's own rule sends
a new reusable pattern to mechanisms.md, and it already points at this
section twice.

Refs #400, #403

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
derek73 added a commit that referenced this pull request Aug 19, 2026
From this session's practice, kept terse because AGENTS.md is loaded
every session:

- review the fix commit too -- second-round passes on #398, #400 and
  #403 each found defects in the first round's fixes
- check the PR description before merging; a review that moves
  behavior leaves it stale, and a stale body reads as authoritative
- a scripted multi-edit that asserts as it goes discards everything
  when a late pattern misses, silently, since prose edits fail no test

mechanisms.md's "check the receiver" field note gains the other half:
ask what the old behavior was CONCEALING. #379's attachment removed
the input a test used to build an all-particle middle name (#402), and
#400's reserve fix exposed the count shape #397 names.

Co-Authored-By: Claude Opus 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.

1 participant