## What
The evolve-cron-rpi loop's phase-1 discovery diffed candidate slices
against a **stale local `main`** (the rpi worktree's local main lags
`origin/main`), so work already merged to `origin/main` read as "open"
and got re-seeded as duplicate beads/PRs (ag-b8m≈ag-jov, ag-6kw≈ag-c2i —
4th recurrence). The `work-selection-ladder` reference *claimed* "the
cron syncs local main to origin/main before discovery" but no code
actually did it.
## Change
- **`skills/evolve/scripts/sync-main-to-origin.sh`** (new): `git fetch
origin`, then fast-forward local `main` to `origin/main` (never forced),
emitting `DIFF_BASE: origin/main <sha>` as the authoritative diff base.
A divergence is refused, never force-moved.
- **`scripts/overnight-evolve.sh`**: runs the sync before the loop's
discovery phase. Non-fatal on warning (loop proceeds with origin/main as
the base).
- **`skills/evolve/references/work-selection-ladder.md`**: the claimed
sync now points at the real, runnable script.
- **`tests/scripts/sync-main-to-origin.bats`** (new): hermetic bare-repo
tests pin the diff base = origin/main after fetch (not stale local
main), local main fast-forwards, divergence is refused, and a custom
remote is respected.
Pairs with the grep-existing-beads guard (`duplicate-work-guard.sh`,
#582) to cover both halves of the bead.
## Gates
- `shellcheck --severity=error` clean on both modified scripts.
- `bats tests/scripts/sync-main-to-origin.bats` — 5/5 pass.
- `git diff origin/main --stat` — scope-only (4 files,
evolve/rpi-discovery surface).
Closes-scenario: ag-6jt#discovery-origin-main
Bounded-context: BC3-Loop
Evidence: skills/evolve/scripts/sync-main-to-origin.sh