Loops ๐Ÿ”

Stop prompting the agent turn-by-turn โ€” design the loop that prompts it. Answer a few questions and Engli compiles a runnable loop: the five blocks, a /goal stop condition, a SKILL.md maker, a separate checker, an on-disk memory spine, token caps, and the failure-mode guardrails.

Design the loop
What should the loop achieve?
How do you KNOW it's done?
a command's exit code or a literal string to grep โ€” not a vibe
Where does each iteration's work come from?
How should a separate checker verify each turn?
What must it NEVER touch?
Compiled loop
# Loop: keep-ci-green-on-the-open-pr

**Goal** โ€” keep CI green on the open PR
**Stops when** โ€” the test suite exits 0 with zero failures
**Mode** โ€” unattended (run while you sleep) ยท cap 10 iterations
**Tool** โ€” both

## The five blocks
1. **Source** โ€” Find the next unit of work from: failing tests. Skip anything already marked done in the state file.
2. **Maker** โ€” Maker: make the smallest change that advances: keep CI green on the open PR
3. **Checker** โ€” Checker (separate agent): verify that `npm test` exits 0 and prints no FAIL lines. Reply PASS or FAIL with one line of evidence.
4. **Memory** โ€” Record: append the finished item to .engli/loop.state.json (done[]), update iteration + notes.
5. **Decide** โ€” Decide: stop when the test suite exits 0 with zero failures; otherwise pick the next item and repeat (max 10 iterations).

## Guardrails (failure modes handled)
- **Evaluator reads the transcript, not your files** โ†’ Echo proof into the transcript each turn (paste the test/lint output the checker greps).
- **Loop never stops (vague condition)** โ†’ Make the stop condition a single command's exit code or a literal string to grep for.
- **Maker also grades itself** โ†’ Split maker and checker into separate agents; only a checker PASS advances the loop.
- **Model forgets prior turns** โ†’ Read + write the on-disk state spine every turn; the repo remembers, the model doesn't.
- **Runaway token spend** โ†’ Cap iterations and total tokens; stop on cap and report, don't silently continue.
- **Unbounded blast radius** โ†’ Constrain the maker to specific paths; forbid deletes/migrations/force-push unless asked.
- **Silent failure looks like success** โ†’ On checker FAIL, fix and retry; after N retries, stop and surface the failure, never merge.
- **Duplicate / redundant work** โ†’ Record completed items in the spine and skip anything already marked done.

Why loops

The maker does one unit of work; an independent checker grades it (only a PASS advances); the result is written to a memory spine the model can't forget; a stop condition decides whether to go again. You design it once and watch instead of type โ€” and the same artifacts run in Claude Code (/goal) or Codex. CLI: python3 -m engli.loops.cli --help.