* fix(scheduler): pause a task whose schedule no longer computes
Admission validates every schedule, but a stored one can stop computing
later: a zone the installed tz database no longer has, or a cron
expression a newer croniter rejects. The scheduler recomputes next_run_at
inside the shared poll, and that raise escaped:
- dispatch_task recomputed it in its except block after a successful
launch, so run_once aborted the claimed batch and left the occurrence
in "launching" with no last_error;
- once the launch lease expired, recover_expired_launch_claims found the
durable run and raised again for every poll, before claim_due_tasks,
so no other scheduled task was admitted for the rest of the process.
Runtime cursor writes (launch, launch repair, queue timeout, launch
failure, finalization) now use stored_next_run_at, which returns the
reason instead of raising. A live recurring task is paused with
"schedule can no longer be computed: ..." as its last_error and no next
run; a once task keeps its normal outcome. Resume re-validates the
schedule, so it reports the problem until the schedule is fixed.
run_once also isolates the lease-recovery pass, like the terminal-run
reconciliation next to it, so a failed pass no longer skips admission.
* docs(changelog): reference #7993 for the unschedulable task fix