Nothing Left to Run
The commit adds one chore to a job that pulls new material from seven feeds, three times a day: once a week, also rebuild the census its own status report uses to judge those feeds. The body ends on two sentences that read like care:
pull.mjs calls it after every real pull, inside the inbox lock, through a lazy import (changes.mjs imports pull.mjs). A failed census logs and never fails the pull.
Both sentences show the author seeing a hazard. The census module already imported the pull module, so importing it back would close a loop. The answer was to load it at run time, inside the function, behind a try. The comment above that try says it twice: loaded only here, and “a census failure must never fail the pull, which is the loop’s heartbeat.”
The next scheduled run fetched its feeds, staged seventeen new items, wrote its heartbeat, reached the census, and exited with status 13. The journal offered one line:
Warning: Detected unsettled top-level await
Nothing threw. The pull module ends in await main() at the top level, so as far as Node is concerned the module is still being evaluated for as long as main() runs. The lazy import asked for the census module, which asked for the pull module, which could not finish evaluating until main() returned, which was waiting on the import. In a runtime with one thread that is not a hang. The event loop runs out of work, and Node quits with the exit code reserved for exactly this.
So the try was never wrong, only idle. A catch handles a promise that rejects; this one never settled, and the line that would have logged “census refresh failed” did not print once. The design kept its word to the letter. The census never failed the pull. It never failed at all.
What the body missed is that the loop it routed around was mostly harmless. In a ten-line reproduction, the plain static cycle runs and exits 0; the run-time import is the version that cannot finish while its importer is still evaluating. The tests saw neither, because they import the pull module, and main() only runs when the file is the entry script.
Eight runs ended that way: four on schedule, plus two re-runs after each of two of them by the supervisor that retries what it cannot classify. Each re-run found nothing new and died identically. Every one had done its work first.
The fix drops the top-level await, keeps the lazy import, and adds a test that runs a copy of the file as the entry script, the one way it ever ran in production.
The census itself was never due. It had been rebuilt by hand the afternoon the commit landed, and the chore would not have come round for a week. All eight runs died asking whether it was time.