## Review of Branch Changes
Here's my review of the branch changes. The diff adds a new `replicate` operation mode (source-authoritative relay-only) across the CLI, library API, planner, and a new `internal/strategy/replicate` package.

### Overall
Solid, well-tested addition. The split between `sync` (reconciliation) and `replicate` (overwrite) is clean. New code is mostly additive, and there's good test coverage at planner, strategy, session, and CLI levels. A few things worth addressing before merge.

### Issues / Nitpicks

1. **Breaking JSON field rename — `execution.mode` → `execution.transfer_mode`** (`pkg/gitsync/internalbridge/model.go:98,145`)
   `ExecutionSummary.Mode` → `TransferMode` is a backwards-incompatible change to the stable embedding surface. If the stability promise matters for `pkg/gitsync`, consumers parsing `execution.mode` will silently break. Either (a) keep `mode` as a deprecated alias, (b) call this out in a CHANGELOG, or (c) confirm no external consumers yet.

2. **Dead/confusing branch in `defaultOperationMode`** (`cmd/git-sync/main.go:412-424`)
   ```
   func defaultOperationMode(name string, defaultMode gitsync.OperationMode) operationMode {
       if defaultMode != "" { return operationMode(defaultMode) }
       if name == "plan" { return operationMode(gitsync.ModeSync) }
       return operationMode(gitsync.ModeSync)
   }
   ```
   The `name == "plan"` branch is identical to the fallback. Just `return operationMode(gitsync.ModeSync)`. Also — `plan` passes `defaultMode=""` intentionally, but `sync` and `replicate` always pass a value, so `name` is never needed. The helper can shrink to `if defaultMode != "" { return … }; return operationMode(ModeSync)`.

3. **`BuildReplicationPlans` mutates its caller's `managed` map** (`internal/planner/planner.go:174-185`)
   The prune branch writes back into the passed-in map. Document the side effect. This is the kind of thing that becomes a bug in 6 months.

4. **`dryRun` argument in `CanReplicateRelay` is effectively dead** (`internal/planner/relay.go:122-124`)
   The only call site is `planner.CanReplicateRelay(false, relayPlans, …)` — hardcoded. Drop the parameter or call it from the dry-run path too.

5. **`runReplicate allAbsent` ignores managed refs that aren't in `desiredRefs`** (`internal/syncer/syncer.go:~555-565`)
   `allAbsent` only scans `desiredRefs`. If prune is on and the target has managed refs to delete while every desired ref is absent, we jump into the bootstrap path, which doesn't handle the deletes. A test for `replicate --prune` against an "empty except for orphaned managed ref" target is worth adding.

6. **`SupportsReplicateRelay` called twice** (`internal/syncer/syncer.go:~548` and again inside `CanReplicateRelay` at `~632`)
   Minor redundancy — `CanReplicateRelay` already calls `SupportsReplicateRelay`. Not wrong, just inefficient readability-wise.

7. **`closeOnce` in the strategy is defensive but unused externally** (`internal/strategy/replicate/replicate.go:83-104`)
   If `gitproto.LimitPackReader` doesn't wrap in a double-close-safe reader, a comment explaining why `closeOnce` exists would save future readers.

8. **Usage string duplication** (`cmd/git-sync/main.go:~410`)
   The huge `fmt.Sprintf` with every subcommand's flags is now ~doubled in length. Splitting it into per-subcommand helpers is advisable.

9. **Replicate relay vs. `--prune` delete flow**
   Adds a test covering `replicate --prune` end-to-end through the `syncer`.

### Nice Touches
- Test server now has a reusable `rewriteReceivePackAdvertisement` helper, cleaner than the previous inline capability mutation.
- `operationModeString` defaulting empty → `"sync"` in both bridges is consistent.
- `replicate` correctly rejects `--force` at session construction with a clear "use sync instead" message.

### Suggested Follow-Ups (not blockers)
- CHANGELOG entry for `TransferMode` rename.
- Document the "replicate fails → retry with sync" semantics in `docs/architecture.md`.

**Test Coverage for Replicate**

- **Planner (`internal/planner/planner_test.go`)** — 4 tests
  - `TestPlanReplicationRefOverwritesDivergence`
  - `TestPlanReplicationRefOverwritesTagRetarget`
  - `TestCanReplicateRelayRejectsNoThin`
  - `TestCanReplicateRelayRejectsInvalidPlanAction`

- **Strategy (`internal/strategy/replicate/replicate_test.go`)** — 1 test
  - `TestExecuteReplicateRelaysUpdatesAndDeletesSeparately`

- **Syncer integration (`internal/syncer/integration_test.go`)** — 2 tests
  - `TestRun_IntegrationReplicateRejectsNoThinTarget`
  - `TestReplicateCanBootstrapRejectsPruneDeletes`

- **Bridge (`pkg/gitsync/internalbridge/model_test.go`)** — 1 test
  - `TestFromSyncResultShapesStableSummary`

- **Public client (`pkg/gitsync/client_test.go`)** — 1 test
  - `TestClientReplicateRejectsUnsupportedMode`

- **CLI (`cmd/git-sync/main_test.go`)** — 1 test
  - `TestRun_Plan_ReplicateMode_JSONShowsReplicate`

### Gaps to Flag
- No happy-path replicate integration test. A green-path integrate test is needed to validate success scenarios. 
- No test for `--force` rejection at session construction.
- No test for `replicate --prune` successfully deleting an orphaned managed ref.
- No test exercising tag replication end-to-end.
- CLI coverage only tests `plan --mode replicate`, not `replicate` itself.
