`FieldMenu.svelte`'s `insertField` (insert left/right) and `FieldManagerDialog.svelte`'s `moveField` (reorder) both build a whole replacement schema array from a caller-supplied reactive `schema` prop and call `updateCollectionSchema` directly. Two rapid schema edits — a reorder racing an insert, two reorders in quick succession, or an edit racing a concurrent collaborator's own field change — can each read a schema that's already stale by the time the second call writes, silently dropping the first change.
PR #200 (issue #189) fixed exactly this race for field-append by adding `records.ts`'s `appendCollectionField`, which reads `ymeta.get('schema')` fresh inside a `doc.transact` rather than trusting a snapshot (flagged by CodeRabbit during that PR's review). `insertField` and `moveField` still have the old, racy shape.
Done when: field insert and reorder both read the schema atomically from Yjs at write time, proven by a regression test that two rapid operations from one snapshot don't drop either change.
`FieldMenu.svelte`'s `insertField` (insert left/right) and `FieldManagerDialog.svelte`'s `moveField` (reorder) both build a whole replacement schema array from a caller-supplied reactive `schema` prop and call `updateCollectionSchema` directly. Two rapid schema edits — a reorder racing an insert, two reorders in quick succession, or an edit racing a concurrent collaborator's own field change — can each read a schema that's already stale by the time the second call writes, silently dropping the first change.
PR #200 (issue #189) fixed exactly this race for field-append by adding `records.ts`'s `appendCollectionField`, which reads `ymeta.get('schema')` fresh inside a `doc.transact` rather than trusting a snapshot (flagged by CodeRabbit during that PR's review). `insertField` and `moveField` still have the old, racy shape.
Done when: field insert and reorder both read the schema atomically from Yjs at write time, proven by a regression test that two rapid operations from one snapshot don't drop either change.