Course · Term 17 of 30
Background Agents
Every lesson in this course builds one system: a stablecoin reserve attestation registry that discovers issuers, reads the PDFs they publish, and refuses to publish a field it could not read. What it is and where this lesson sits.
A scheduled job with a model in it. The scheduling is ordinary — cron has existed for forty years — and saying so is the honest start.
What changes is that nobody is watching. Term 18 removed the human from a run; this removes them from the decision to start one, and that adds three failure modes attended work does not have.
Overlap. The previous run has not finished when the next one fires. Two agents, same job, same paths, which is interstitial II happening on a timer.
Drift. A run fails and the next starts from the failed state, compounding rather than retrying.
Silence. A run fails and nothing says so, because the thing that would have noticed is the person who is not there.
The interesting design is not the schedule. It is what the job does when it is wrong and nobody is looking.
The mechanism
admit() decides before any work happens, and the order of its checks is the
design:
- Halted first, because a job that stopped itself must not be restarted by a schedule. Only a person clears it.
- Overlap next, because a second concurrent run is worse than a missed one.
- The write gate last, and still pre-flight. A job that discovers mid-run that it may not write has already done something.
settle() counts consecutive failures. Three in a row halt the job. A retry
that never gives up is not resilience — it is a loop producing the same wrong
answer at a regular interval, and the streak converts an unattended failure
into a stopped job, which is a state a human eventually notices.
The receipt
artifacts/17-scheduled.json, twelve firings:
run outcome streak reason
1 ok 0 completed
2 skipped 0 previous run has not finished; overlapping the same job
3 ok 0 completed
4 ok 0 completed
5 failed 0 the job returned a non-zero exit
6 failed 1 the job returned a non-zero exit
7 failed 2 the job returned a non-zero exit
8 refused 3 halted after 3 consecutive failures; a person must clear it
...
ok 3, failed 3, skipped 1, refused 5
halted after run 7
a job trying to write outside its directory: refused — worktree-containment
Failures and overlaps are supplied rather than sampled, so the timeline is identical on every machine. A simulation of unattended flakiness that is itself flaky teaches nothing.
The timeline that tested nothing
The first version put the failures at runs 4–6 and the overlap at run 9. The job halted at run 6, so the overlap was never reached — that entire path went untested while the demo printed a tidy table and exited zero.
The overlap has to happen while the job is still alive. The demo asserts a skip occurred, which is what caught it.
Break it first
mutation tests demo
overlapping runs allowed 2 failed | 11 passed exit 1
the job never halts itself 2 failed | 11 passed exit 1
streak counts cumulative, not consecutive 2 failed | 11 passed exit 0
The third is the subtle one. Counting cumulative failures instead of consecutive ones halts every long-lived job eventually, no matter how healthy — a job failing once a fortnight stops after six weeks. The test that catches it alternates failures and asserts the job never halts.
Where it overlaps
Line D is execution surface, and this is the rung past headless: not merely unattended during a run, but unattended in deciding to run. Term 18 is the substrate; term 28 is where this stops being a habit and becomes a pipeline. Line F is determinism wrapping stochasticity — the admission gate is the deterministic part, and it is the only part that will still behave when nobody is watching. Line H is isolation, because an overlapping job is a fan-out nobody chose.
A personal teaching project, in development. The registry it builds is a teaching artifact and is not an assurance opinion about any issuer. Not affiliated with or endorsed by any employer, or by any vendor whose tools it describes. Where a unit depends on a specific flag or path, it names the version it was verified against. All units.