Skip to content

Fix directional annotation tie boundaries - #556

Open
johnml1135 wants to merge 1 commit into
masterfrom
fix-506-directional-boundaries
Open

johnml1135 wants to merge 1 commit into
masterfrom
fix-506-directional-boundaries

Conversation

@johnml1135

@johnml1135 johnml1135 commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Start here: src/SIL.Machine/DataStructures/BidirList.cs, Find: the whole source change is a 9-line edit there.

Status: first of a stack — merge in order #556 → #500 → #480 → #578.

Ready for review. CI has no red checks (the claude-review job was skipped).

BidirList.Find now descends to level zero before returning an equal node, so it selects the first match in the requested search direction. Before, an equal node found on a higher skip-list level was returned at once, so word copying and segment deletion could land on the wrong member of a tied annotation group. The fix is in the shared lookup, and the tests are deterministic fixed layouts.

Reviewers arrive asking how a change to a shared data-structure lookup is pinned. Every case in AnnotationTieTests runs over 200 seeds (skip-list shapes), and reverting only the lookup change breaks most of them. The question worth your time: does returning the first tie in the search direction match what callers of Find expect when they pass an offset that starts or ends a tie?

Where to look:

  • BidirList.Find: both directions must reach the correct edge of an equal-range group. Pinned by Find_ReturnsFirstMatchingAnnotationInSearchDirection and GetNodes_ReturnsAnnotationsAtBothTiedBoundaries.
  • Word copy and clone: mapped ranges and payloads survive. Pinned by CopyAndClone_PreserveMappedAnnotationRangesAndPayloads.
  • Node removal: exact survivors, and tied children under shrinking multi-node owners. Pinned by RemoveNode_PreservesExactUnaffectedAnnotations, RemoveStartEndpoint_ShrinksMultiNodeOwnerAndRemovesEveryTie and RemoveEndEndpoint_ShrinksMultiNodeOwnerAndRemovesEveryTie.

Not here:

Verification (run on the earlier commit d98d12a5; the head differs only by src/AssemblyInfo.props from a rebase onto master): ./local_check.sh --agent-strict passed; focused AnnotationTieTests passed with 0 failed, 0 skipped. Not run: this branch combined with #557. Details in the accordions.

Next: approve, or say which Find caller needs a test for the new boundary.


Reading this a year from now -- start here

Addresses #506's directional tie-boundary mechanism (#506 is an open issue). Related: #500, #480, #554, #555. The reasoning and evidence scope live here because the PR description is the only record.

Evidence
  • ./local_check.sh --agent-strict: passed with one-node WSL settings and the existing native CI build output restored; all normal stages ran.
  • AnnotationTieTests: six test methods, each over 200 seeds, so 1,200 cases at the head (recounted). Earlier run on d98d12a5: 1,200 passed, 0 failed, 0 skipped, independently rerun.
  • Fix-removed check of the 1,200-case suite on a separate worktree, reverting only the lookup change: 977 failed, 223 passed. Restoring the fix returned the suite to green.
  • git diff --check origin/master...HEAD: passed. An independent source and test review passed.
  • Ten fresh-process corrected-oracle runs matched the complete two a and five ga identity multisets, including application order, morph order, allomorph index and features.
Native prerequisite and evidence scope

Base 259920414132bdd5a85542722d9af5509aed8943, candidate d98d12a5d514ce589d7495c71d055830e061a418.

The WSL environment lacks CMake. The existing sp4c-linux-x64 output from the successful exact-base CI run was restored after verifying the native wrapper's source inputs were unchanged. Its required tcmalloc runtime was downloaded, hash-checked and extracted under task-private /tmp; no system package was installed and no product dependency changed. The strict gate used a command-scoped LD_LIBRARY_PATH for that runtime.

The full local script does not collect CI-equivalent coverage. The finite identity checks and deterministic layouts establish the exercised cases; #554 and #555 remain separate findings.

Generated with OpenAI Codex.


This change is Reviewable

@codecov-commenter

codecov-commenter commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.62%. Comparing base (74ee09b) to head (579b2ef).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #556      +/-   ##
==========================================
+ Coverage   74.57%   74.62%   +0.04%     
==========================================
  Files         453      453              
  Lines       38314    38317       +3     
  Branches     5280     5281       +1     
==========================================
+ Hits        28573    28594      +21     
+ Misses       8576     8561      -15     
+ Partials     1165     1162       -3     

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

return true;
}

break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: F1. The public Find(start, example, dir) overload can now return a tie that comes before start, and which tie it returns depends on random node levels. Example: start S ties example with Levels == 2, and tie T (level 1) sits between S.GetPrev(1) and S. Before this change the call returned S; now it drops to level 0 and returns T. If S has Levels == 1, it still returns S. Nothing in src/ calls this overload (searched for Find( in src/), so the visible effect is limited to outside callers. Unverified: I reasoned this through but did not reproduce it.

@claude

claude Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor
  1. Verdict: approve. BidirList.Find now goes down to level 0 before it returns a match, so Shape lookups find the first tie in each direction.
  2. Most important: F1 (Low), src/SIL.Machine/DataStructures/BidirList.cs:273. The Find(start, ...) overload can now return a tie that comes before start. Nothing in src/ calls it.
  3. Counts: Critical 0, Important 0, Low 1.
  4. Ran the focused tests (AnnotationTieTests, AnnotationTests, SkipList, ShapeTests) at the PR head: 1,205 passed, 0 failed, 588 ms. CI gh pr checks 556: both builds (ubuntu-22.04, windows-latest) pass; Create NuGet package is pending.
  5. Not verified: I did not reproduce F1 with a test, and I did not run the HermitCrab conformance fixtures from the PR body.

Public API / TFM / package / machine.py parity: the return-value behavior of the public BidirList.Find overloads changed: with ties, they now return the first match in the search direction, where before they returned whichever match the search reached first. Signatures are unchanged. BidirList has no sillsdev/machine.py counterpart.

Findings: F1 new, unverified.

Reviewed at d98d12a

johnml1135 added a commit that referenced this pull request Oct 24, 2026
Pin full parse multiplicity and application histories from combined Machine
#500 and #556 in three derivatives of the #480 truncation grammar. Update
fixture-derived coverage, interaction ledgers and their audit pins.

The original grammar is unchanged. The complete expectations intentionally
remain red on the conformance branch until both engine fixes are applied.
@johnml1135
johnml1135 force-pushed the fix-506-directional-boundaries branch from d98d12a to 579b2ef Compare October 26, 2026 11:50
johnml1135 added a commit that referenced this pull request Oct 26, 2026
Pin full parse multiplicity and application histories from combined Machine
#500 and #556 in three derivatives of the #480 truncation grammar. Update
fixture-derived coverage, interaction ledgers and their audit pins.

The original grammar is unchanged. The complete expectations intentionally
remain red on the conformance branch until both engine fixes are applied.
@johnml1135
johnml1135 requested a review from jtmaxwell3 October 27, 2026 12:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants