Build package / php-lint (8.2) (push) Successful in 58s
Build package / php-lint (8.3) (push) Successful in 41s
Build package / php-lint (8.4) (push) Successful in 36s
Build package / xml-lint (push) Successful in 12s
Build package / unit-tests (push) Successful in 38s
Build package / package (push) Successful in 58s
Job::start() calls setLastRun() before run() and clears `reserved_at` only afterwards through setExecutionTime(), which is not in a finally block. Any uncaught throwable therefore leaves the job reserved, and JobList::getNext() skips reserved jobs until the reservation is 12 hours stale -- so a single failing workflow takes the whole app offline for half a day, while last_run still shows the start of that failed attempt. Wrap both loops so a failure is logged with its exception and the remaining users and workflows still run.