step 1 of 7 · dispatch
You say one sentence, anywhere dispatch listens.
No template, no form. Dispatch triages it: this is product work, it deserves an intent. It files the change and the first item — you are already done for now.
actor: dispatch · your cost: one sentence
step 2 of 7 · the intent expands
The intent expands: questions fan out.
An intent loop wakes and frames the work: what has to be true before anyone writes code? The open questions become items — the frontier of the change.
actor: intent loop · your cost: nothing yet
export-backoff/ ├── intent.md the sentence, framed ├── questions │ ├── #312 retry, queue, or shed load? │ └── #313 what does the API's Retry-After promise? └── sessions/ empty — no one has worked it yet
step 3 of 7 · a session works the round
A design session works the questions.
In its own worktree it reads the export client, probes the API's actual rate-limit behaviour, and writes up the options with evidence — retry with backoff, a send queue, or load shedding.
actor: design session · your cost: nothing yet
rate-limit-shape/ ├── findings.md API returns Retry-After on 429 — honoured? yes ├── options.md backoff vs queue vs shed — costs of each └── README.md what this session did and why
step 4 of 7 · the plan
The round closes into one screen.
Everything the session settled — and everything it proposes next — lands as one plan: answers seeded, a decision drafted, a unit of construction proposed, sometimes the next round. Nothing on this screen exists on GitHub yet.
actor: the session, assembling · your cost: still nothing
step 5 of 7 · your word
One word contracts the round — and can expand the next.
You correct what's wrong — a route, a type, an answer typed into a row — and approve once. The retry decision becomes a record in the change, the unit drops into construction — and the test-hardening round opens only because you said grow.
actor: you, on the rim · your cost: one word
# Decision — how exports survive rate limits Retry with exponential backoff, capped at 5 tries. Honour Retry-After when the API sends it. A send queue is out: it hides latency instead of surfacing it. Closed by the operator, 2026-08-12.
step 6 of 7 · build — the bolt runs
Past your approval, construction runs without you.
The bolt gives each approved change its own spec, an independent review, then a build agent in a nested worktree. The design book the decision landed in is the spec's source of truth — not a memory of a conversation.
actors: bolt loop + construction sessions · your cost: none
@@ send() — on 429 @@- throw new ExportError(res.status);+ const wait = retryAfter(res) ?? backoff(attempt); // decisions/retry-shape.md + if (attempt < 5) return this.retry(req, attempt + 1, wait); + throw new ExportError(res.status);
step 7 of 7 · merged
Evidence climbs back out.
Acceptance runs on the bolt branch, the final checks pass, the work lands on main — and the landing is reported back so the intent checks its task off. The journey leaves a spec trail the whole way down. And the round you opened with the same word is already turning — that is the flywheel in motion.
actor: bolt loop · your cost: none — you already spoke
9f21c04 feat(export): retry with capped backoff, honour Retry-After
Seven steps, one spec trail
Your cost, totalled: one sentence, a few minutes of annotation, one word. Everything else ran on its own ring — and every step handed the next one something written down. The rings turn at 1 : 2 : 6 : 24, and every turn leaves spec behind.
back to the walk ↩ · same journey, other ideas: onboarding email order → · dashboard dark theme →