fix(maiden): a marker stops the particle chain that swallowed it - #409
Open
derek73 wants to merge 2 commits into
Open
fix(maiden): a marker stops the particle chain that swallowed it#409derek73 wants to merge 2 commits into
derek73 wants to merge 2 commits into
Conversation
`Ursula von der Leyen geb. Albrecht` lost the maiden name that `Ursula Leyen geb. Albrecht` kept: grouping's prefix chain absorbed everything up to the next prefix or suffix piece, and the marker is consumed AFTER the chain merges, by which point there is no lone marker piece left to find. rules.md carried that as an Accepted limitation, but it was a consequence of stage order rather than a judgment, so M2 now states the stop and the limitation is gone. The chain's stop and the maiden handler's consumer share one definition of a marker piece. A chain that stopped where the consumer would not then take would strand the marker inside the family name -- the very defect the stop exists to fix. Two shapes it fixes for free. Under a family-first order the marker used to survive as an ordinary name word and take the leftover given slot (`de la Cruz née Vega` -> given 'née'); dropped, it never reaches the placement, which answers #399's open question with no second change. And stopping the chain can leave a family of nothing but particles, which #404's R2 reading already covers: `Jane de la née Jones` reports family 'de la' with a non-empty base. Tests are the whole verification here. No differential corpus name has a particle ahead of a marker, so the gate is blind to this class and its clean exit says nothing about it. Closes #399 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
derek73
force-pushed
the
fix/399-maiden-marker-stops-chain
branch
from
August 19, 2026 08:36
b633270 to
829de84
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #409 +/- ##
=======================================
Coverage 98.55% 98.55%
=======================================
Files 44 44
Lines 2977 2981 +4
=======================================
+ Hits 2934 2938 +4
Misses 43 43 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Review found the first cut of #399 traded one stranding for a worse one. Sharing a marker-piece predicate between the chain's stop and the maiden consumer settles what a marker piece IS; it does not settle whether the consumer TAKES, because the consumer also needs a non-suffix piece after the marker. Stopping without one left the marker standing as its own piece, and a lone trailing piece takes a role field: Jane van der Berg née was middle 'van der Berg', family 'née' The marker became the surname and the real surname was demoted -- the defect the stop exists to prevent, one field over. The stop now tests the consumer's own condition, so the two halves cannot disagree. Three measured consequences, each fixed by the gate. 'Jane van der Nee' moved a bearer of the attested surname Nee out of the family, which M1 already warns about. 'Ursula von der Leyen geb.', an ordinary truncated record, reported the marker as the surname. And 'St St née' stopped reporting its particle-or-given fork, because group's emitter is guarded on the chain having merged something and an ungated stop made it merge nothing for a different reason than the guard assumes -- an A1 violation of the shape #405 tracks, and worse, since it removes a report callers already see. Pinned six ways: four case rows and two piece-level tests in test_group.py. The piece level is where the two halves can disagree without any field looking wrong enough to fail -- the misaligned version passed the entire suite. Also from review: - Two limits the deleted Accepted clause used to cover are back in M2, scoped: the bound reaches only a lone marker, so P3's connective join and P5's bound-given join each still absorb one first. #399 fixed one instance of the join-swallow and left two. - P2's statement enumerated the join's stops and named neither the marker nor the suffix. Both are stated now, and its two code citations move with it. - The new normative sentence moved ahead of M2's examples, because the citation checker cuts a statement at its first example line -- stated after them, it could never be cited from code. - decisions.md: the false invariant is corrected, the quoted removal is verbatim so `git log -S` finds it, and the recorded reason for preferring the stop over a stage reorder is rewritten. The example it cited does not discriminate: 'Anna Müller geb. von der Berg' is identical before #399, after it, and under a reconstructed reorder. - A release_log.rst bullet, which the first commit omitted. - Three case notes corrected: one claimed only the maiden field moved when the family moved too, one credited R2 for what P4 and P1 do, and one promised a pin the partition invariant does not deliver. - 'Jane née and Jones Smith' pins the marker predicate's lone-piece guard, which was an unkilled mutant: dropping it left 4229 tests green while changing behaviour through a conjunction merge. - The cross-script row puts a name of this shape in the CJK corpus, so the class is gate-visible for the first time, with its own ledger rule and recorded corpus claim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #399.
Ursula von der Leyen geb. Albrechtlost the maiden name that the same words one particle chain apart kept:The fix
Grouping's prefix chain absorbs everything up to the next prefix or suffix piece, and the maiden marker is consumed after the chain merges — by which point there is no lone marker piece left to find. The chain now stops at a marker the way it already stops at a suffix.
Only a non-leading particle ever reached the marker, which is why a leading single particle always worked (P4 chains nothing) while a leading run of two did not — the second particle's own chain fired.
The stop is gated on the consumer actually taking
This is the substance of the change, and it came out of review rather than the first cut. Sharing one marker-piece predicate settles what a marker piece is; it does not settle whether the consumer takes, because the consumer also needs a non-suffix piece after the marker. Stopping without one left the marker standing as its own piece, and a lone trailing piece takes a role field:
The marker became the surname and the real surname was demoted — the defect the stop exists to prevent, one field over. The gated reading is also what M2 already said should happen: a marker with nothing after it "is just a word", exactly as
Jones née→family='née'.Three measured consequences of the ungated form, each closed by the gate:
Jane van der Neemoved a bearer of the attested surname Nee out of the family. M1 already names Nee as a surname.Ursula von der Leyen geb.— an ordinary truncated record — reported the marker as the surname.St St néestopped reporting itsparticle-or-givenfork. Group's emitter is guarded on the chain having merged something, and an ungated stop made it merge nothing for a different reason than the guard assumes: an A1 violation of the shape A tussenvoegsel attachment decides a particle-or-given fork and reports no ambiguity, which A1 requires #405 tracks, and worse than A tussenvoegsel attachment decides a particle-or-given fork and reports no ambiguity, which A1 requires #405's, because it removes a report callers already see.Two shapes fixed without a second change
Ursula von der Leyen geb. Albrechtloses the maiden name — a particle chain swallows the marker where a suffix stops it #399's open question. Under a family-first order the marker used to compete for the leftover given slot, sode la Cruz née Vegareportedgiven='née'. Consumed and dropped, it never reaches the placement, and both family-first orders now agree. A marker the consumer declines still reaches it — that is M2's "just a word" reading, not a leak.Jane de la née Jones→family='de la'with a non-empty base, via Should a particle that joins nothing still count as a particle? (Jong van derandJong, van deralready disagree) #404's R2 reading. A 305,364-parse sweep at review found no empty-base or partition violation either side of the change.Limits, now stated rather than implicit
The bound reaches only a marker standing as a word of its own, so P3's connective join and P5's bound-given join each still absorb one first —
Jane van der Berg née y Jonesandvan der Berg, abdul née Jonesare unchanged. The deletedAccepted:clause covered a class of which this fixes one instance and leaves two; both survivors are back in M2 with examples.Docs
rules.md#M2: the stop and its gate are in the statement, ahead of the examples — the citation checker cuts a statement at its first example line, so a rule stated after them can never be cited from code.rules.md#P2: its statement enumerated the join's stops and named neither the marker nor the suffix. Both are named now, and its two code citations move with it.decisions.md#M2: the false invariant is corrected; the quoted removal is verbatim sogit log -Sfinds it; and the recorded reason for preferring the stop over a stage reorder is rewritten, because the example it cited does not discriminate —Anna Müller geb. von der Bergis identical beforeUrsula von der Leyen geb. Albrechtloses the maiden name — a particle chain swallows the marker where a suffix stops it #399, after it, and under a reconstructed reorder.docs/release_log.rstgets its Behavior Changes bullet, which the first commit omitted.Verification
Tests carry it, and the class is now gate-visible for the first time. No corpus name had a particle ahead of a marker, so the harness was blind to this shape; the cross-script case row puts one in the CJK corpus, with its own ledger rule and recorded corpus claim. All three baselines exit clean (1.4.0, 2.0.0, 2.1.0), the 1.4.0 baseline verified genuine rather than the mislabelled cached tree.
20 case rows plus two piece-level tests in
test_group.py. The piece level matters because that is where the two halves can disagree without any field looking wrong enough to fail — the misaligned version passed the entire suite. Removing the gate now fails 6 tests; dropping the marker predicate's lone-piece guard, previously an unkilled mutant, now fails 2.Full suite green: 4293 passed. ruff and mypy clean,
_group.pyand_post_rules.pyat 100% statement and branch coverage.🤖 Generated with Claude Code