# ADR-071: Fresh Pre-Create Dedup Re-check at Dispatch | Field | Value | |-------|-------| | **Decision ID** | ADR-071 | | **Initiative** | unsorry Phase 3 — verifier capacity efficiency | | **Proposed By** | unsorry maintainers | | **Date** | 2026-06-18 | | **Status** | Accepted | ## WH(Y) Decision Statement **In the context of** ADR-064's goal-level dispatch dedup, where `dispatch_queue` fetches `origin/main` and lists open prove PRs **once at pass start** and then opens up to `UNSORRY_DISPATCH_LIMIT` PRs from the queued branches, **facing** duplicate "already proved on main" PRs that kept re-appearing **after** ADR-064 shipped (every closed duplicate — #2059, #2081, #2123, #2131, #2150, #2164, #2174, #2179 … — was created after #1952 merged), because the pass-start snapshot goes **stale during the pass**: a sibling proof of the same goal can MERGE, or a concurrent dispatcher can OPEN a PR, between the pass-start checks and the actual `gh pr create` — so the branch is dispatched into a dead duplicate that first-merge-wins then strands as un-mergeable, **we decided for** a **final fresh re-check immediately before each create**: `goal_taken_fresh` re-fetches `origin/main` and re-lists open prove PRs, and `dispatch_queue` skips the branch if the goal is now proved or already has an open PR — run only for the handful actually being dispatched (after the governor gate), using a `git grep` + one core-API list (never the 30/min search API, ADR-064), **and neglected** a fully atomic cross-process dispatch lock (a millisecond TOCTOU remains between the fresh check and `gh pr create`; deferred — the window shrinks from minutes-per-pass to milliseconds, and first-merge-wins keeps any residual duplicate sound, just wasteful), and fixing the upstream prove-time race that produces sibling branches in the first place (still the deeper ADR-064 follow-up; this closes the dispatch-side leak that actually produced the observed dead PRs), **to achieve** a dispatcher whose "one PR per goal" holds across the duration of a pass and against concurrent dispatchers, ending the recurring sweep of already-proved duplicates, **accepting that** each actual dispatch now costs one extra `git fetch origin main` + one `gh pr list` (bounded by the dispatch limit, core quota), and the check is best-effort — any git/gh error degrades to "not taken" so dispatch is never blocked by infra health. ## Context Amends ADR-064. ADR-064 stopped *same-pass* and *pass-start-known* duplicates; this ADR closes the *stale-snapshot* window that let post-064 duplicates through. The change is confined to `swarm/agent.sh` `dispatch_queue` plus the `goal_taken_fresh` helper, and is hermetically self-tested (`test_dispatch_skips_taken_midpass`). ## Options Considered ### Option 1: Fresh pre-create re-check (Selected) **Pros:** directly kills the observed leak; tiny, contained; reuses ADR-064 helpers; affordable (per-dispatch, not per-branch); no search API. **Cons:** a millisecond TOCTOU remains before `gh pr create`. ### Option 2: Atomic cross-process dispatch lock (Rejected for now) A git-ref / lease lock so only one dispatcher acts on a goal at a time. Fully closes the TOCTOU but adds a lock lifecycle and failure modes; deferred since the fresh re-check reduces the window to negligible and first-merge-wins keeps residual duplicates sound. ### Option 3: Fix the upstream prove-time race (Rejected as scope) Stop sibling branches forming at claim time. The deeper ADR-064 follow-up; larger claim-protocol change. This ADR fixes the dispatch-side leak that produced the actual dead PRs; the prove-time race remains tracked. ## Dependencies | Relationship | ADR ID | Title | Notes | |--------------|--------|-------|-------| | Amends | ADR-064 | Goal-Level Dispatch Deduplication | Adds the fresh pre-create re-check ADR-064's pass-start snapshot misses | | Depends On | ADR-018 | index proved marker | `goal_already_proved` reads `library/index` | | Relates To | ADR-058 | Runner Pool Segmentation and Verification Capacity | Dispatcher is the consumer | ## References | Reference ID | Title | Type | Location | |--------------|-------|------|----------| | REF-1 | SPEC-071-A — Fresh pre-create dedup re-check | Specification | specs/SPEC-071-A-Fresh-Dispatch-Dedup-Recheck.md | ## Status History | Status | Approver | Date | |--------|----------|------| | Proposed | unsorry maintainers | 2026-06-18 | | Accepted | unsorry maintainers | 2026-06-18 |