Overreach

Never proposed the simpler way

从不提出更简单的做法

The agent delivers a working but over-complicated, verbose solution. It rarely says that a smaller change would do, that something isn't needed, or that the change shouldn't be made at all.

Applies to: Claude Code · Cursor · Codex · Copilot agent

Symptom

Roundabout control flow, extra layers and long comments where a few lines would do. Human reviewers keep leaving the same comment, "there's a simpler way", and the diff shrinks a lot once they do.

Why it happens

In replies to Thorsten Ball's PR post, @lawrjones says he steers the code in 40% of the PRs he merges, often for architectural choices or over-complication where Opus didn't see a simpler path. @akepka_: even frontier models "will rarely tell you that something is not needed or could be 10 times simpler". @isaacvando often asks to close a PR or redo it in a way that fits the project and notes Codex never suggests closing one. @LucaColonnello sees "silly roundabout ways of doing things" and a lack of questioning why something is needed. @clintwinter13 catches "overly verbose code and bad design"; @benjaminhonorio catches code that is overcomplicated or unnecessary; @GrmlBob finds Opus code badly bloated on big projects; @motziabuelnasr reviews agent PRs that turn out complex to reason about or not scalable; @zeenix finds AI-generated docs and comments unreadable for humans. Agents implement the request as given, and pushing back on its size or necessity is rarely rewarded.

Example

Illustrative.

ts
// Asked: show the user's display name, falling back to their email
class DisplayNameResolverFactory {
  create(strategy: "name" | "email" = "name") { return new DisplayNameResolver(strategy); }
}
// ...60 more lines...

// Simpler:
const displayName = user.name || user.email;

Copy-paste fixes

Pick the files for the agents you use. Snippets are in English so they work in any repo.

Rules

Claude Code: add to CLAUDE.md

CLAUDE.md
## Propose the smallest change first
- Before writing code, state the smallest change that would satisfy the request. Implement that
  unless the user asks for more.
- If you believe the request isn't needed, or a much simpler approach exists (including reusing
  existing code or not making the change), say so first and let the user choose.
- No new classes, layers, factories or config options unless the request needs them.
- Comments explain why, briefly. Don't narrate what the code does.
- In your summary, name one thing you chose not to build and why.
Rules

Codex, Copilot coding agent and others: add to AGENTS.md

AGENTS.md
## Propose the smallest change first
- Before writing code, state the smallest change that would satisfy the request. Implement that
  unless the user asks for more.
- If you believe the request isn't needed, or a much simpler approach exists (including reusing
  existing code or not making the change), say so first and let the user choose.
- No new classes, layers, factories or config options unless the request needs them.
- Comments explain why, briefly. Don't narrate what the code does.
- In your summary, name one thing you chose not to build and why.
Cursor rule

Cursor: project rule

.cursor/rules/never-proposed-the-simpler-way.mdc
---
description: "AgentFails: Never proposed the simpler way"
alwaysApply: true
---

## Propose the smallest change first
- Before writing code, state the smallest change that would satisfy the request. Implement that
  unless the user asks for more.
- If you believe the request isn't needed, or a much simpler approach exists (including reusing
  existing code or not making the change), say so first and let the user choose.
- No new classes, layers, factories or config options unless the request needs them.
- Comments explain why, briefly. Don't narrate what the code does.
- In your summary, name one thing you chose not to build and why.
CI / script

Diff budget check (run before commit or in CI)

Adapted from the diff-budget post on dev.to (yureki_lab). Reads the real git diff, so it also catches edits made through the shell. Usage: python3 scripts/diff_budget.py origin/main 6 150

scripts/diff_budget.py
#!/usr/bin/env python3
"""Fail if the diff vs BASE touches files outside .agent-scope or exceeds the budget."""
import fnmatch, os, subprocess, sys

base = sys.argv[1] if len(sys.argv) > 1 else "HEAD"
max_files = int(sys.argv[2]) if len(sys.argv) > 2 else 6
max_lines = int(sys.argv[3]) if len(sys.argv) > 3 else 150

allowed = []
if os.path.exists(".agent-scope"):
    allowed = [l.strip() for l in open(".agent-scope") if l.strip() and not l.startswith("#")]

out = subprocess.run(["git", "diff", "--numstat", base], capture_output=True, text=True, check=True).stdout
untracked = subprocess.run(["git", "ls-files", "--others", "--exclude-standard"],
                           capture_output=True, text=True, check=True).stdout.split()

files, lines, outside = 0, 0, []
rows = [r.split("\t") for r in out.strip().splitlines()] + [["0", "0", p] for p in untracked]
for added, deleted, path in rows:
    files += 1
    if added != "-":
        lines += int(added) + int(deleted)
    if allowed and not any(fnmatch.fnmatch(path, p) for p in allowed):
        outside.append(path)

problems = []
if outside:
    problems.append("out-of-scope files: " + ", ".join(outside))
if files > max_files:
    problems.append(f"{files} files changed (budget {max_files})")
if lines > max_lines:
    problems.append(f"{lines} lines changed (budget {max_lines})")

if problems:
    print("OVER BUDGET: " + "; ".join(problems))
    sys.exit(1)
print(f"within budget: {files} files, {lines} lines")
Skill

Fresh-context review skill (subagent reviews the diff, not the chat)

Follows the habit Anthropic describes in its code-review post: verify first, then have a subagent review the diff with fresh context. Named review-diff to avoid clashing with built-in or popular /code-review skills.

.claude/skills/review-diff/SKILL.md
---
name: review-diff
description: Review the current diff with fresh context before a PR. Use after /verify passes.
---

# Review the diff

Start a subagent that has NOT seen this conversation. Give it only:
- the original request (one paragraph, verbatim),
- the output of `git diff origin/main...HEAD`,
- the names of the test/build commands.

Ask it to report, with file:line for each finding:
1. **Wrong feature**: does the diff do what the request asked? Quote the request line each change serves.
2. **Bugs**: logic errors, missing edge cases (empty, null, boundary), unhandled errors,
   unawaited promises, invented APIs or packages, swallowed exceptions.
3. **Overreach**: changes no request line needs (refactors, renames, formatting, dependency or
   config edits, public API changes, weakened tests).
4. **Evidence gaps**: claims in the PR description that no command output supports.

Then fix real findings, or list them under "Known issues" in the PR. Do not argue with the reviewer
in the PR text; either fix or explain in one line.

Sources and credit

Related patterns

翻车 of the week

One real agent failure and its fix, every week. Free, short, no spam.