Give a strong coding agent a thin instruction and it fills the silence with initiative: “add CSV export” arrives with a scheduling system; “fix the login bug” arrives with a refactor of your session layer. None of it was asked for. All of it must now be reviewed.
Why agents over-build
Three reasons, all structural. The prompt states the goal but not the boundary. The agent can't see what customers didn't ask for. And nothing tells it which adjacent “improvements” your team already decided against — so it re-litigates settled questions in code.
The three mechanisms that fix it
- 1. A Non-goals fence. The plan enumerates the tempting adjacencies and forbids them by name. Not “keep it minimal” — “do not build date-range, action-type, or resource filters.”
- 2. Cited acceptance criteria. Every criterion traces to a customer quote. If a feature has no source id, it doesn't go in the plan — the strongest possible prior against invented scope.
- 3. Contradiction gates. Work that would reverse a recorded decision is blocked with an ⚠ UNRESOLVED marker until a human explicitly approves the override in a comment.
Wire it into the agent, not the human
The mechanisms only work if the agent reads them before acting. That's what AGENTS.md is for — the instruction file Claude Code, Codex, Cursor, and OpenClaw all load automatically. scriptonia init writes the contract into it once: execute PLAN.md exactly, respect Non-goals, stop on UNRESOLVED, cite sources in the PR. After that, the discipline is ambient — no one has to remember to paste it.
The one-line takeaway
Scope is data, not vibes. Put the boundary in a file the agent must read, derive it from what customers actually said, and gate it on what your team already decided. The agent stops over-building the day the boundary stops living in your head.