Resilience
A closed lid is not a crash
An unattended run has to survive the ordinary interruptions of an unattended machine — sleep, a dropped network, a killed process — without losing work or wedging. Zecor treats the git branch and the on-disk queue as the source of truth, never the process's memory, so any of those can happen mid-task and the next run picks up exactly where it left off.
State lives on disk, not in memory
Everything a run knows lives in one of three stores, and none of them can be torn mid-write:
| State | Lives as | Why an interruption can't corrupt it |
|---|---|---|
| Task progress | a git branch |
open_lane checks out a worktree per task and every attempt
commits or resets against it — an interrupted run leaves real,
inspectable git history, not a half-finished diff in a dead process.
|
| Task queue | card files |
written with a tmp-file-plus-os.replace swap — a reader
sees the old card or the new one, never a half-written one.
|
| Quota ledger | SQLite, WAL mode | crash-safe by construction. |
Restart after any interruption and the state that matters was never only in RAM to begin with.
Sleep, lid-close, crash
Every in-flight task holds a lease with an expiry, and a lease past its expiry is normally treated as abandoned and picked up by the next run. What actually happens turns on one question: is the holder still alive?
ready, not to some special
recovery state, so the same dispatch path that picks up a fresh task
also picks up an interrupted one.
The remote link
Watching or steering a run from a phone means the connection itself has to
survive roaming between towers, backgrounding the app, and walking through a
dead zone — the machine running Zecor is almost never the problem, the link to
it is. zecor remote setup wires three pieces, each with one job:
Gives the phone a stable address to the machine over an encrypted WireGuard link that punches out through carrier NAT on its own — no port forwarding, nothing to configure on a router.
Keeps the console session running on the machine independent of whether anything is attached to it.
Replaces the fragile SSH-style connection with one that tolerates IP changes, sleep, and dead zones — close the phone, walk out of signal, reopen it later, and the session is still there, not disconnected.
None of that makes the run itself more durable — the state-on-disk model above already does that. It means losing the view into a run costs nothing either.
What this doesn't cover yet
Honestly: two pieces of the resilience story are still hardening rather than finished.
- Local-model reconnect. A local model endpoint that drops mid-attempt is reported as a failure today, not yet retried with backoff.
- Wall-clock deadlines everywhere. A deadline measured against wall-clock time (so a long sleep can't look like a three-second timeout, and a real three-second timeout can't look like a sleep) is audited in the places that matter most, not universally yet.
Neither is silent — both fail loud and recoverable, never silently wrong.