Fix a dropped morpheme ID when a zero-width rule wraps one ending at the same node - #500
Open
johnml1135 wants to merge 1 commit into
Open
johnml1135 wants to merge 1 commit into
johnml1135 wants to merge 1 commit into
Conversation
johnml1135
force-pushed
the
fix/signature-drops-id-under-identity-rule
branch
from
September 25, 2026 19:12
b15073b to
96d6b7f
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #500 +/- ##
=======================================
Coverage 74.07% 74.07%
=======================================
Files 456 456
Lines 38164 38164
Branches 5228 5228
=======================================
+ Hits 28270 28271 +1
Misses 8734 8734
+ Partials 1160 1159 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…the same node In SynthesisAffixProcessAllomorphRuleSpec.ApplyRhs, a zero-width rule's fallback "no new output morphs" marking claimed the shared final shape node before the loop that re-marks the wrapped rule's own morph, so the wrapped rule's morpheme ID could be overwritten or ordered ahead of the outer rule's. Move the fallback marking after that loop so the wrapped allomorph keeps its ID and the outer rule's ID sorts after it. Adds IdentityRuleSignatureMorphDropTests with two deterministic controls and one regression that retries fresh language loads. Measured over 100 fresh loads: with the fix, the correct signature is reached 41/100 times; with the fix reverted, 0/100 -- confirmed by reverting the production change and rerunning. The remaining gap under the fix is a separate, unfixed ordering defect (tracked in #506); this PR does not make output deterministic for every ordering, only reachable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
johnml1135
force-pushed
the
fix/signature-drops-id-under-identity-rule
branch
from
September 25, 2026 22:54
96d6b7f to
5aa7b39
Compare
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.
Quick summary
Copy-only rules now preserve a wrapped affix's morpheme ID when both rules mark the same trailing shape node.
The fix only makes the correct signature reachable (41/100 fresh loads); the rest trace to a separate, unfixed ordering defect (#506).
Only two files change: one reordered marking call and one new HermitCrab regression test.
Where to look
SynthesisAffixProcessAllomorphRuleSpec.ApplyRhs-- the reordered fallback marking that fixes the drop.IdentityRuleSignatureMorphDropTests-- two deterministic controls plus thefenosregression, which retries up to 100 fresh language loads.Deliberately not included
Validation
dotnet build Machine.sln-- Build succeeded, 0 Warning(s), 0 Error(s).dotnet test tests/SIL.Machine.Morphology.HermitCrab.Tests/SIL.Machine.Morphology.HermitCrab.Tests.csproj --no-build --no-restore-- Passed: 108, Failed: 0, Skipped: 0.dotnet csharpier check .-- Checked 720 files, no issues.pwsh -NoProfile -File scripts/comment-hygiene.ps1 -BaseRef origin/master--comment-hygiene: clean (lines added since origin/master (merge base 7109531e)).Reading this a year from now
SynthesisAffixProcessAllomorphRuleSpec.ApplyRhsmarks morphs on the output shape in two places: a fallback for rules with no new output morphs (truncation and zero-width rules, such as a copy-onlyCopyFromInput), and a loop that re-marks each input morph the rule wraps. When a zero-width rule's own affix and an inner wrapped rule's affix end at the same trailing shape node, whichever call runs second keeps that node's morpheme ID. The fallback used to run first, so the outer rule's ID could overwrite or precede the wrapped rule's. Moving the fallback after the loop makes the wrapped rule's ID stick and the outer rule's ID sort after it, matching the order the fixture inIdentityRuleSignatureMorphDropTestsexpects.Decisions, and why
The
fenostest retries up to 100 fresh loads and passes on the first correct signature. Measured: 41/100 correct with the fix, 0/100 with it reverted. Asserting every attempt would be red even with the fix; a single assertion would be flaky. Retry-until-first-success is the one assertion the data supports, and it goes red with the fix reverted.An earlier comment blamed
BidirList's unseeded skip-list levels. The source does not support that: same-range annotations tie-break onAnnotation.ListID, a call-order counter. The claim was removed.Deferred, and what would unblock it
Making every fresh parse deterministic needs the separate ordering defect tracked in #506 fixed first; this PR does not attempt that, since the true source of the per-run variation is not yet identified (it is not
BidirList's level randomization, per the reading above).Prior measurements (superseded)
An earlier revision of this PR body reported "five green repetitions; suite 575 passed, one skipped, zero failed" and a seed experiment claiming "12/12 repeatability versus three unseeded outputs," attributed to forcing a fixed seed on
BidirList'sRandom. Those numbers were not reproduced here and the causal claim they rested on did not hold up against the source; the 41/100 and 0/100 counts above are the current, directly measured replacement.🤖 Generated with Claude Code
This change is