Only the principal pull recorded its target (mark_move) before git wrote the
tree. The first branch switch in _prepare_checkout_for_update (and its
`checkout -B` fallback), a fork's early and late upstream sync, and the
post-pull syntax rollback wrote the tree unrecorded: a torn switch or sync at
an unmoved HEAD was judged against whatever refs a later fetch left, and a
failed second move (upstream sync after a successful pull) had no baseline at
its starting HEAD at all, so the gate admitted the torn tree.
All of them now run inside _checkout_move(token, *targets). Before git runs it
persists the resolved target(s): on the pause's own baseline when the step
starts from the pause HEAD (it knows the edits already there), otherwise on a
new baseline taken at the step's starting HEAD with its dirty digests. A
record that cannot be written raises, so the step does not run. Once git
returns, a per-step baseline is retired if HEAD moved or the tree is exactly as
the step found it, so a clean refusal never holds the set. The upstream sync
takes the context as `checkout_move`; the pull's move is extracted to
_move_checkout_to so _pull_updates does not nest deeper.