Skip to content

Fix spurious CFC SetOrder during fwdata→crdt sync#2304

Merged
myieye merged 4 commits into
developfrom
claude/fix-cfc-singleton-setorder
May 28, 2026
Merged

Fix spurious CFC SetOrder during fwdata→crdt sync#2304
myieye merged 4 commits into
developfrom
claude/fix-cfc-singleton-setorder

Conversation

@myieye

@myieye myieye commented May 27, 2026

Copy link
Copy Markdown
Collaborator

During sync the same logical CFC is reached twice — once via SyncComplexForms on the component-side entry (no between), again via SyncComplexFormComponents on the complex-form entry with BetweenPosition(null, null) for a singleton. The second call found the existing CFC and, because between was non-null, fell through to MoveComplexFormComponentPickOrdermax + 1, emitting a spurious SetOrderChange that bumped Order 1→2 (and further on repeat syncs).

CreateComplexFormComponent now treats (null, null) as "no positional intent", matching the normalisation OrderPicker.PickOrder and FwDataMiniLcmApi.InsertComplexFormComponent:1137 already apply.

Surfaced in a real DB: 243 of 365 FieldWorks-authored SetOrderChange events were on CFCs that are the only sibling on their complex form.

Test plan

  • CreateComplexFormComponent_BetweenWithNoAnchors_DoesNotReorderExisting in ComplexFormComponentTestsBase (runs against both LcmCrdt and FwData implementations — FwData already honoured the contract).

🤖 Generated with Claude Code

myieye and others added 3 commits May 27, 2026 12:47
The orderable diff in EntrySync hands BetweenPosition(null, null) to Add
when no stable neighbours exist (e.g. a singleton component). During sync
the same logical CFC is reached twice — once via SyncComplexForms on the
component-side entry (no between) and once via SyncComplexFormComponents
on the complex-form entry (between with both neighbours null). The second
call found the just-created CFC and, because between was non-null,
fell through to MoveComplexFormComponent → PickOrder → max+1 every time,
emitting a spurious SetOrderChange that bumped Order from 1 → 2 (and
further on repeated syncs).

CreateComplexFormComponent now treats `(null, null)` as no positional
intent — same boundary normalisation OrderPicker.PickOrder and
FwDataMiniLcmApi.InsertComplexFormComponent already do. New test in
ComplexFormComponentTestsBase exercises both API implementations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Names the predicate shared by OrderPicker.PickOrder (the create branch's
"no positional intent" shortcut) and the new CreateComplexFormComponent
guard. The CRDT site's previous inverted pattern read awkwardly; both
callsites now use the same null-tolerant helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7c96cd12-c2bb-4e2c-afb5-b5a051b15ab5

📥 Commits

Reviewing files that changed from the base of the PR and between 6d2cf1a and c54c002.

📒 Files selected for processing (2)
  • backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs
  • backend/FwLite/MiniLcm.Tests/ComplexFormComponentTestsBase.cs

📝 Walkthrough

Walkthrough

The PR adds a guard condition in CreateComplexFormComponent to skip reordering when BetweenPosition has no anchors (both Previous and Next are null), preventing unintended order changes during replay. A test validates this behavior.

Changes

Between-position singleton guard

Layer / File(s) Summary
Prevent reordering on empty between anchors
backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs, backend/FwLite/MiniLcm.Tests/ComplexFormComponentTestsBase.cs
CreateComplexFormComponent checks that between.Previous or between.Next is non-null before moving an existing component, preventing order changes from singleton (null, null) anchors. A new test verifies that creating a component with empty anchors preserves the order of an existing component.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Possibly related PRs

Poem

🐰 A guard stands firm at the between,
When anchors both turn null and lean,
No reorder shall wrongly flow—
The component's order stays, we know!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main fix: preventing spurious SetOrder changes for singleton ComplexFormComponents during fwdata→crdt sync, which is the core change.
Description check ✅ Passed The description comprehensively explains the sync issue, the root cause (treating non-null between as positional intent), the fix applied, and provides real-world impact data, all directly related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fix-cfc-singleton-setorder

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related label May 27, 2026
@argos-ci

argos-ci Bot commented May 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Awaiting the start of a new Argos build…

@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

UI unit Tests

0 files   -   1  0 suites   - 59   0s ⏱️ -32s
0 tests  - 176  0 ✅  - 176  0 💤 ±0  0 ❌ ±0 
0 runs   - 245  0 ✅  - 245  0 💤 ±0  0 ❌ ±0 

Results for commit 2e466d7. ± Comparison against base commit 6d2cf1a.

♻️ This comment has been updated with latest results.

Keep just the WHY: where (null, null) comes from and what skipping the
move prevents. The full sync trace belongs in the commit history, not
the source.

Co-authored-by: Claude <noreply@anthropic.com>
@myieye myieye merged commit c83114c into develop May 28, 2026
8 of 11 checks passed
@myieye myieye deleted the claude/fix-cfc-singleton-setorder branch May 28, 2026 08:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant