ef6ce56cad
A direct run (cronjob action='run' / webhook-triggered manual fire) takes the job's fire_claim and advances next_run_at. When it races the external provider's scheduled fire for the same occurrence, Chronos loses the claim and — by design — does not re-arm (the winner owns the re-arm). But the direct-run winner never notified the provider, so the NAS one-shot for the consumed occurrence was left stale forever and the recurring job silently stopped firing. Observed in production: a managed 1-minute review job stalled for 20 hours because a GitHub-webhook direct run claimed the job 2s before the Chronos fire arrived; every subsequent occurrence was orphaned while /api/status stayed green. Fix: after a *claimed* direct execution completes (success or failure — next_run_at advances at claim time either way), call _notify_provider_jobs_changed_safe() so the active provider re-arms the post-run next_run_at. No-op for the built-in ticker; claim-lost direct runs still never notify (the winning scheduler owns the re-arm).