Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions docs/AUTONOMOUS-LOOP.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,69 @@ fires one final time, then deletes itself."* For runs
longer than 7 days, the `long-term-rescheduler` skill rotates
crons near expiry via `CronDelete` + `CronCreate`.

## Invariant — rediscoverable from `main` alone

This discipline serves a load-bearing invariant:

> **A fresh agent reading `main` alone — no chat history,
> no in-session memory, no out-of-band context — can pick
> up the next tick and continue the work cleanly.**

The every-tick checklist below is *a* mechanism that
preserves this invariant; it is not itself the invariant.
The number of checklist steps is incidental — discoverability
from `main` alone is what's load-bearing.

Concretely, every change to this file MUST preserve (or
strengthen) the invariant. The check is: *can a freshly
spawned agent, reading only committed-on-`main` artifacts,
find the prior tick's state and act on it?* If yes, the
invariant holds. If no, the change has broken it.

Four properties make the invariant true today:

- **Tick-history is on `main`.** Each tick lands a row in
`docs/hygiene-history/ticks/YYYY/MM/DD/HHMMZ.md` before
the tick stops, so the next session sees the prior tick's
context by reading the repo.
- **PR queue is on the host.** Open PRs are visible via
`gh pr list` without session state; the next tick can
poll the gate (real-dependency-wait discipline) without
remembering which PRs are in flight.
- **Substrate precedes narration.** Decisions, corrections,
and framings land as memory files / backlog rows / docs
in committed substrate BEFORE chat narration. Per
substrate-or-it-didn't-happen (Otto-363) +
non-durable-means-does-not-exist (the human maintainer,
2026-04-30), if it isn't on `main`, the next tick
won't see it.
- **Cron is the cadence engine, not session memory.** The
every-minute heartbeat fires whenever a session is active
to receive it; `CronList` is checked end-of-tick so the
[last-check → next-fire] window is minimized; the next
tick fires without depending on the prior tick's
process state. Sessions that resume via `--resume` /
`--continue` inherit the registered cron when it's still
within its 7-day expiry; brand-new sessions re-arm via
the every-tick checklist (per the "Session-restart
recovery" section below).

Future revisions of this file may add, drop, or restructure
the checklist below — provided the rediscoverable-from-`main`
invariant is preserved or strengthened. Treat the four
properties above as the test surface.

> The human maintainer, 2026-04-30 (paraphrased — the original
> framing was "Six-step tick close has a satisfying property
> that should be an invariant for all future changes to this
> file" followed by a sharpening "not six step the
> rediscoverable on main part"; the bracketed gloss reflects
> the sharpening): *"[the rediscoverable-on-main part]
> should be an invariant for all future changes to this
> file."* The meta-property is what makes the discipline
> portable across sessions, agents, and forks of the
> factory.

## The every-tick checklist

This is the load-bearing bit. **Every tick**, in order:
Expand Down
Loading