get_due_jobs() called load_jobs() twice: once for filtering (with _apply_skill_fields) and once for saving updates. Between the two reads, another process could modify jobs.json, causing the filtering and saving to operate on different versions. Fix: load once, deepcopy for the skill-applied working list.