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

main

Commit

nodo2w ago

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

Checkpoints

Fix Silent Field Drops in Git Sync Configuration

Claude CodeOpus 5.[1m]
View session
Checkpoint 1

Fix Git Sync Source Scope Handling

Claude CodeOpus 5
View session
Checkpoint 1