fcbdcdb428
The future-instant guard in claim_job_for_fire dropped the occurrence identity for ANY claim ahead of the stored next_run_at. A hosted/webhook fire for the armed slot that arrives a few seconds early (the fire scheduler's clock runs ahead of ours) was therefore treated as an off-tick run: it ran occurrence-free, mark_job_run recomputed the same cron slot from a now still before it, and the tick/misfire backstop then ran the slot a second time. Only claims at least FIRE_CLAIM_SKEW_SECONDS (60 s) ahead of the slot are now classified off-tick, so dashboard/manual far-future fires stay occurrence-free while a skewed early fire keeps the slot identity. completed_occurrence honours the same window so the early run's completion row (finished just before the slot) still proves the slot done instead of being discarded as poison. Review finding: claim_job_for_fire future-instant guard had no skew tolerance; an early hosted fire for the armed slot ran twice.