mst: prune subtree nodes emptied by delete
deleteFromNode recursed into a child subtree and marked the parent dirty
but never dropped the child when the delete emptied it. MST nodes are
content-addressed, so the emptied node serialized as a real block and
changed every ancestor CID — the tree no longer equalled the tree that
never contained the key, which is the equality commit-proof inversion
depends on. The TS reference prunes here (deleteRecurse: remove the entry
when the returned subtree has no entries); we only trimmed at the root.
Effect: verifyCommitDiff returned PrevDataMismatch for valid second
commits from a real PDS. Any repo with two records whose keys differ in
height hits it — the lower key lives alone in a subtree, and inverting
its creation must prune that subtree.
Found downstream in zlay through the atmoq relay-conformance corpus,
where the sync11/commit2-valid control was being dropped.
Existing coverage missed it three ways: the lazy-vs-eager delete test
asserts the two paths agree rather than that either is right; the
interop commit-proof fixtures only delete high keys at or above the root
layer; and the verifyCommitDiff test builds its own fixture, inverts an
update rather than a create, and ships the whole tree instead of a
partial proof. Both new tests fail without the prune: one pure-MST, and
one golden fixture generated by @atproto/repo carrying a real partial
proof.
See REPORT-mst-inversion-prevdata.md.