Keep the batched resume marker when the target refuses the branch create
Commit

The batched cutover deleted its temp ref on the strength of a nil push error, and under BestEffort that error covers the request rather than each command in it: the pusher hands a per-ref "ng" to OnRejection and returns nil. So a target that refused the branch create — protected branch, pre-receive policy — ended the run with neither the branch nor the marker, reported as a success. With nothing on the target pointing at the objects already pushed, the next run had no have to negotiate against and re-transferred the whole history, on precisely the large repositories batching exists for (ENT-1948, >10 GiB). Reachable wherever best-effort is implied: --all-refs turns it on for bootstrap and sync, and client.go passes Policy.BestEffort through for any mode.
The rejection now reaches the strategy. Params.Rejected is a predicate the syncer answers from the map it already fills from the pusher's OnRejection callback, and the cutover consults it before deleting: a create this run cannot confirm leaves the marker at the final checkpoint, so the next run resumes from it. The delete is made conditional rather than dropped the way PR #116 dropped the one-shot path's: Bootstrap() rejects --prune outright, so on that route no cleaner would ever exist and the marker would be permanent.
The kept marker is also recorded as a completed ref, since it genuinely holds that hash — the objects behind it stay usable as haves for the branches planned after this one. The rejection itself was already surfaced honestly (Pushed 0, Warned 1, plan action=warn); what was surfaced nowhere is that the run also destroyed the checkpoint, so retaining it now logs and prints a line naming the marker and the hash it resumes from.
Tests: the pinned test from this branch now passes, and a companion asserts the half that makes the marker worth keeping — the retry, once the target accepts the create, finishes the import from the marker (zero checkpoint packs, 334 bytes to the target against the first run's 427 KiB) and only then deletes it. Both share the receive-pack denier the first test introduced, now a type carrying the reason it cannot use syncertest.DenyRefsReport.
Remaining items on ENT-2060 are untouched: partial-progress subset resume, a sync-mode route, and stale markers under --map or branch-scoped prune.
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com Claude-Session: https://claude.ai/code/session_018BKBGBh3rJ6WGnZKDbBRy7 Entire-Checkpoint: 01M1BRMEV28MA421RDYNHM4X7C