claim_task was a blind UPDATE (`WHERE id = ?`), so two agents racing to
claim the same task both 'succeeded' — last writer wins. This is the exact
contention the Tailscale bridge exposes once remote agents poll the board.
Guard the UPDATE on `status = 'queued'` so the claim is atomic: only the
first claimant matches a still-queued row; the rest match zero rows and get
a new StoreError::Conflict (surfaced as ok:false over the socket). A zero-row
result is disambiguated into NotFound vs Conflict.
Tests:
- test_claim_task_is_exclusive / test_claim_task_not_found (store)
- socket_rejects_double_claim_of_same_task (daemon, end-to-end over socket)
Plan: Gap 4 moved to closed. Store 11 green, board 4 green, clippy clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>