## TL;DR

The merge run died partway, leaving some pairs merged and some not, with no record of which. Keep a persistent ledger (pair, status, result), retry only the unmerged pairs, and verify at the end that every pair reached a terminal state. The ledger is the fix, not the retry logic.

## Error

```text
(No error; the symptom is a merge run that stopped with an unknown mix of merged and unmerged pairs.)
```

## Steps

1. Build the ledger from what you can observe: query the CRM for each pair's current state. Expected: you reconstruct merged vs unmerged.
2. Write the ledger to durable storage before retrying anything. Expected: the ground truth is safe.
3. Retry only pairs still unmerged, marking each as you go. Expected: no double-merges.
4. For pairs that fail again, record the reason in the ledger and move on. Expected: failures are explicit, not silent.
5. At the end, verify: every pair is merged, failed with reason, or explicitly skipped. Expected: a complete, auditable run.

## When to use

- A merge run crashes or is killed partway.
- Rerunning merges causes "already merged" errors.
- You cannot tell what a failed run accomplished.

## When not to use

- Merge failures from bad data (fix the pair first).
- Planning a merge run (build the ledger in from the start).

## Tool compatibility

- Any merge API; a ledger in a file or database.
- Agent retry loops.

## Variant phrasings

### partial merge failures

Ledger and retry the remainder.

### unknown merge state after crash

Reconstruct from the CRM, then ledger.

## Why it happens

Merges are destructive and non-idempotent, and runs without a ledger cannot distinguish "not attempted" from "failed". A crash in that state is unrecoverable without manual forensics.

## Edge cases

- "Already merged" errors on retry are expected; treat them as success and update the ledger.
- Concurrent merge runs need a shared ledger or they will double-merge; coordinate.
- Ledger writes must happen before the merge call returns, not after, or a crash loses the record.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_9prcYtJe6XM38ZQ9EfKL3Q
