Severity
High — the sync action creates duplicates instead of fixing differences.
What happens
syncToTarget sends [...diff.added, ...diff.changed] with operation = 'insert' whenever the match field isn't an External ID (the default match field is Name; Id is excluded from the SELECT and stripped before push). A record classified Changed already exists in the target — inserting it creates a duplicate row, and the field difference the user wanted to fix remains. Concrete: match on Name, sync a Changed Account with a differing Phone → the target ends up with two "Acme" Accounts, the original still holding the old Phone.
Evidence
src/ui/screens/DataComparisonScreen.tsx:158-177 (insert for changed), :104 (default Name), :98-99/:162 (Id excluded/stripped)
Suggested fix
Include target Id in the comparison query and push Changed records as update against d.targetRecord.Id; insert only Added records.
Environment
Commit 74cf21b (main), WaveLink 0.6.0. Found in the 2026-08-31 adversarial audit (code-verified).
Severity
High — the sync action creates duplicates instead of fixing differences.
What happens
syncToTargetsends[...diff.added, ...diff.changed]withoperation = 'insert'whenever the match field isn't an External ID (the default match field isName;Idis excluded from the SELECT and stripped before push). A record classified Changed already exists in the target — inserting it creates a duplicate row, and the field difference the user wanted to fix remains. Concrete: match on Name, sync a Changed Account with a differing Phone → the target ends up with two "Acme" Accounts, the original still holding the old Phone.Evidence
src/ui/screens/DataComparisonScreen.tsx:158-177(insert for changed),:104(default Name),:98-99/:162(Id excluded/stripped)Suggested fix
Include target
Idin the comparison query and push Changed records asupdateagainstd.targetRecord.Id; insert only Added records.Environment
Commit
74cf21b(main), WaveLink 0.6.0. Found in the 2026-08-31 adversarial audit (code-verified).