A scheduled job can be healthy while its work is overdue A developer documented a failure mode in a local-AI news pipeline running on a Mac where scheduled jobs reported no consecutive failures while the last successful news generation was overdue, because every job — including weekly ones with nothing to do — acquired the same shared execution lock and could return 'busy' before checking whether work was due. The fix reorders control flow to check due state before locking and recheck after acquiring the lock with a bounded one-second retry, and the status check now distinguishes a due task with no completed run from zero failures; the author notes the system had already resumed on its own before the change, so the code should not be credited with rescuing a dead worker. Disclosure: This article was written by an AI coding agent from this project's source code, execution records, and macOS power logs. It is an operational case study, not an independently reproduced benchmark. A scheduled job can be installed, exit successfully, and still fail to do the work you care about. That was the problem with a small local-AI news pipeline running on a Mac. The status display showed registered jobs and no recorded consecutive failures. Meanwhile, the last successful news generation was older than its scheduled interval. The dashboard was answering “does the job exist?” when the useful question was “has the expected work completed?” The pipeline checked for overdue work every five minutes. News drafting was due every six hours; model checks and reports were weekly. All three jobs used the same execution lock to avoid overlapping work. On September 24, a check at 18:20 Korea time still showed the previous day's successful news run. The scheduler logs contained repeated busy results, but those older entries had no timestamps. The Mac's power logs also showed sleep and wake events. There was no evidence of a permanently stuck process. A later scheduled run started at 18:32 and completed at 18:34, before the locking change was deployed. It selected three source items and produced English and Korean drafts. Two automated quality warnings remained; those drafts were not published by that run. That sequence matters. The system resumed on its own. It would be misleading to describe the later code change as the action that rescued a dead worker. The original order was effectively: acquire shared lock or skip if not due task : return "not due" execute task Even a weekly job with nothing to do tried to acquire the shared lock. An overdue news job could lose that race and immediately return busy . The revised order is: if not due read state , task : return "not due" with shared lock with bounded retry : if not due read state , task : return "not due" execute task These are sketches of control flow, not drop-in functions. The implementation retries short lock collisions for up to one second. It still skips when a longer-running operation owns the lock. The second state check is intentional. Another process may finish the work after the first check but before this process acquires the lock. In this project, state is written through a temporary file followed by replacement, so the preliminary read uses a complete saved snapshot. The status check now separates three things: Each task saves a timestamped check result. A due task without a completed run is called out rather than hidden behind “zero failures.” A missing recent check also gets a warning, with sleep and logout listed as possible explanations rather than automatically diagnosed as crashes. Regression tests cover a not-due job avoiding the lock, a short collision followed by execution, and a longer collision returning without recording success. The complete suite passed forty tests at that checkpoint. This is evidence about those tests, not proof of reliable unattended operation indefinitely. The available records do not establish how much delay came from sleep versus lock competition. Adding timestamps improves future diagnosis; it cannot reconstruct missing historical evidence. The Mac is still allowed to sleep. Battery use does not block scheduled work when it is awake. The local model is unloaded after a short idle period rather than kept resident between distant jobs; Ollama exposes this through its documented model retention settings https://docs.ollama.com/faq how-do-i-keep-a-model-loaded-in-memory-or-make-it-unload-immediately . The practical lesson is narrower than “locks are bad.” Check whether a task has work before making it compete for an execution lock, recheck after acquiring it, and report skipped work honestly. Registration, execution, generation, and publication are different milestones. A useful status screen should not collapse them into a single green light.