Lesson 4 of 6
Run one bounded plan–code–test–fix loop
Give OpenCode one criterion, hard file and command bounds, stopping rules including no test weakening, and a run log with a real stop reason.
You own the brief, the stop, and the merge
The agent does the middle of the loop: plan, small change, run checks, fix. You write the brief, stop the run, and decide whether to keep the diff. OpenCode does not have a built-in test runner and does not stop when tests pass. It runs npm test through bash if you allow that command.
Write the loop down before you start:
Brief (one criterion, allowed files, budget)
→ plan the smallest change
→ implement
→ run the named checks
→ on fail: read the message, fix, or stop
→ on pass: report evidence and stop
If the criterion is unclear, stop and ask. Guessing a requirement is how unbounded sessions start.
Bound files, commands, and iterations before the first edit
The starter includes the complete opencode.json and AGENTS.md.example. Copy the latter to the filename OpenCode reads:
cp AGENTS.md.example AGENTS.md
opencode debug config
Read the resolved permissions before starting a session. The configuration allows source edits, asks for test edits, denies config edits, git push, arbitrary web fetch/search, and external directories. It caps Build at 15 steps. AGENTS.md adds the human workflow: do not weaken a test, stop after three failures of the same check, do not push or deploy.
Permissions gate tool requests; they are not an operating-system sandbox. Read every requested command and never approve a compound command that escapes the agreed task. steps limits agent iterations, not dollars. The wall-clock budget is yours to enforce. Do not pass --auto; it approves requests that are not explicitly denied.
Stopping rules, including test weakening
Stop when any of these is true: (1) the named criteria pass, plus npm test and npm run typecheck; (2) the same check fails three times — that is your rule, written in the brief; (3) the agent deletes, skips, renames, or weakens a test; (4) a file outside the brief changes; (5) the step cap or your wall-clock budget is hit; (6) the criterion is ambiguous.
OpenCode’s doom_loop permission is different: it fires when the same tool call repeats three times with identical input, and it defaults to ask. It does not detect “the same test failed three times with new stack traces.” Do not treat those as the same control.
Test weakening includes swapping a specific assertion for toBeTruthy, not.toThrow(), or a snapshot of anything, and changing expected values to match current output. Refuse that edit. If it already landed, restore the test and call the run failed.
Record the run; review the diff yourself
Pick one criterion that is still not covered or failing (filter-without-delete is a good candidate). Paste a brief that lists allowed files, forbidden files, the exact commands (npm run typecheck, npm test), the step cap, a 30-minute wall-clock budget, and the stop rules.
Keep a run log with real commands and real output:
| Round | Action | Command | Result |
| plan | … | — | approved |
| 1 | … | npm test | 24 passed, 1 failed (quote the error) |
When it stops, write the stop reason in those words: success, repeat failure, test weakening, scope break, budget, or ambiguity. Run git diff yourself. One sentence: why this change addresses the cause. Snapshots plus /undo revert in-session edits; that is not a production rollback.