Ask the planner what the target ref map means, instead of re-deriving it
Commit

Bugbot caught that the divergence check's idea of scope was exclusions-only, while the planner's is wider: with Mappings set, addPruneCandidates declines to manage unmapped branches and other namespaces too. A mapping-pinned mirror whose target held any unmapped branch was therefore reported as permanently diverged over a ref the run would neither push nor prune — the same false divergence the exclusion filter fixed, defeating the very case the pre-planning path exists to serve.
The cause is that "does this request manage this target ref" had been written out three times, so a fourth copy would repeat the mistake. It is now planner.PruneTarget, which addPruneCandidates and the divergence check share. replicateCanBootstrap deliberately keeps its own broader branch rule (under AllRefs a stale branch matters even with a Branches filter set), which is identical to this one wherever AllowEmptySource applies, since that policy requires AllRefs.
PruneTarget normalizes its config rather than assuming a normalized one: syncer.planConfig does not normalize, and reading the raw config is silently wrong in the dangerous direction — an AllRefs request still carrying a Branches filter reports a branch as unmanaged when the request would in fact prune it, so the run converges over a populated target instead of refusing. Both behaviors are pinned by tests that fail if the fix is reverted.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com Claude-Session: https://claude.ai/code/session_01JvpGRBapBppY4xh2x38kDL Entire-Checkpoint: 01M0K3Y9622187AV0J1TCK78X1