What
reconcile's per-item value display (renderItemValues in internal/cli/reconcile.go) prints the header
and then renders dmp.DiffMain(dst, src, false). In diffmatchpatch, deletions come from the first text and insertions from the second, so the [-…-] fragments are destination bytes and the {+…+} fragments are source bytes: the opposite of what the header promises.
Repro
Source mcp/github.toml has command = "npx"; the rendered ~/.claude.json is edited to "npm". agentsync reconcile shows:
--- source
+++ dest
{
"command": "np[-m-]{+x+}",
"type": "stdio"
}
m (the destination's edit) is shown as removed and x (the source's value) as added. Read with the header, that says the destination reverted to the source, when the user did the reverse. [w]rite-back and [o]verride decide which side wins, so the diff's direction is exactly the thing the user is reading it for.
Fix
Either swap the arguments (DiffMain(src, dst, false)) so the markers match the header, or swap the header lines. Swapping the arguments is the smaller change and keeps the conventional "old = source, new = destination" reading. A test that drifts one value and asserts the marker sides ([-x-]{+m+} for the repro above) would pin it; TestReconcile_DroppedServer_WriteBackRemovesSource and the FinishRunsExactlyOnce fixtures already produce this transcript.
Scope note
Pre-existing at 309fde0 (identical in the pre-#232 binary's transcript); surfaced by the round-4 test-rigor review of #253, whose new dropped-server test made the transcript visible in-repo. Out of #253's behaviour-preserving scope. Both value-display sites (the prompt and [d]iff) call the same function, so one fix covers both.
What
reconcile's per-item value display (renderItemValuesininternal/cli/reconcile.go) prints the headerand then renders
dmp.DiffMain(dst, src, false). Indiffmatchpatch, deletions come from the first text and insertions from the second, so the[-…-]fragments are destination bytes and the{+…+}fragments are source bytes: the opposite of what the header promises.Repro
Source
mcp/github.tomlhascommand = "npx"; the rendered~/.claude.jsonis edited to"npm".agentsync reconcileshows:m(the destination's edit) is shown as removed andx(the source's value) as added. Read with the header, that says the destination reverted to the source, when the user did the reverse.[w]rite-backand[o]verridedecide which side wins, so the diff's direction is exactly the thing the user is reading it for.Fix
Either swap the arguments (
DiffMain(src, dst, false)) so the markers match the header, or swap the header lines. Swapping the arguments is the smaller change and keeps the conventional "old = source, new = destination" reading. A test that drifts one value and asserts the marker sides ([-x-]{+m+}for the repro above) would pin it;TestReconcile_DroppedServer_WriteBackRemovesSourceand theFinishRunsExactlyOncefixtures already produce this transcript.Scope note
Pre-existing at
309fde0(identical in the pre-#232 binary's transcript); surfaced by the round-4 test-rigor review of #253, whose new dropped-server test made the transcript visible in-repo. Out of #253's behaviour-preserving scope. Both value-display sites (the prompt and[d]iff) call the same function, so one fix covers both.