scope-discipline
verifiedf05cfca9-fbec-4d8e-aa44-940e092c81b1
Do exactly what was asked — no gold-plating, no unrequested refactors or dependency additions — and ask before expanding scope. Use to keep changes small, reviewable, and reversible.
Metadata
Skill file
# Scope Discipline
Use when executing a task — do exactly what was asked, flag (don't silently make) adjacent "improvements", and ask before expanding scope.
## The Minimal-Diff Rule
**Change only what the task requires.** Every line in your diff must be traceable to the stated requirement.
```bash
# Before finishing, audit your diff for scope creep
git diff --stat # how many files changed?
git diff # is every hunk justified by the task?
```
For every hunk, ask: *"Is this required by the task, or did I do it 'while I was in here'?"* If the latter — it's scope creep.
## Resisting "While I'm Here" Edits
| Temptation | Correct behavior |
|---|---|
| "I'll fix this unrelated bug too" | Fix it only if asked; otherwise note it in a separate report |
| "I'll refactor this messy function" | Flag it; don't bundle it into a bug fix |
| "I'll add this dependency that'll be useful later" | Never add unrequested dependencies (YAGNI) |
| "I'll reformat the file to match style" | Only if the task touches it; else note it |
| "I'll add error handling everywhere" | Add where the task requires, not as a global sweep |
### The out-of-scope list
```markdown
## Out of scope (flagged, not done)
- `utils.py:42` has a bug where `None` input crashes (unrelated to this task)
- The `PaymentService` has no retry logic — worth a follow-up ticket
- `config.py` is missing type annotations
```
Deliver this list separately. Let the user decide whether to act on it.
## When to Ask vs Proceed
Decision table:
| Situation | Action |
|---|---|
| Small, reversible, clearly implied by the task | **Proceed** |
| Small, reversible, but NOT asked for | **Proceed but flag it** in your report |
| Expensive or risky (schema change, data migration) | **Ask first** |
| Opinionated (style, naming, architecture choice) | **Ask first** |
| Irreversible (deleting data, force-push, breaking API) | **Ask first** |
| Adds a new dependency | **Ask first** |
| Changes public behavior/contract | **Ask first** |
```markdown
❌ WRONG — silently expanding scope
"While fixing the login bug, I also migrated the DB schema,
upgraded Django, and added Redis." (nobody asked, huge risk)
✅ RIGHT — flag and ask
"Fixed the login bug (the requested change).
Separately noticed: the DB is on Django 3.2 which is EOL.
Want me to plan that upgrade as a separate task?"
```
## The Scope Boundary Test
If your diff contains changes that would survive *independently* of the requested fix, they're a separate change and should be a separate commit/PR/task.
```bash
# Each logical change = its own commit = reviewable independently
git commit -m "fix: correct login redirect on expired session" # the task
git commit -m "docs: update README with new env var" # separate, flag it
# (don't squash them into one "various fixes" commit)
```
## Worked Example: The Right Way vs the Wrong Way
Task: "Fix the bug where login redirects to the wrong page on expired session."
```diff
❌ WRONG — 400 lines across 12 files
- Rewrote the whole auth module "while I was here"
- Upgraded Django 3.2 → 5.0
- Added a Redis session store (new dependency)
- Reformatted every file to 100-char lines
- Fixed 3 unrelated bugs found along the way
+ The login fix itself is ~15 lines, buried in the noise
```
```diff
✅ RIGHT — 15 lines in 1 file
+ Fixed the redirect logic in session.py (the actual bug)
+ Added a regression test for the expired-session redirect
- (Out-of-scope list, reported separately:)
- - Django 3.2 is EOL — recommend a separate upgrade ticket
- - session.py has a latent None-input bug worth a follow-up
```
The right version is reviewable in 30 seconds, revertible in one `git revert`, and the user can act on the flagged items *if they choose to*.
## Reviewing for Scope Creep (as a reviewer)
When reviewing someone else's PR, apply the same discipline:
```bash
# Isolate the scope of the stated change vs the actual diff
git diff main...feature-branch --stat
```
| Question to ask | Red flag |
|---|---|
| Does this hunk relate to the PR title/description? | No → scope creep |
| Are there reformatting-only changes in untouched files? | Yes → noise |
| Was a new dependency added without discussion? | Yes → block or ask |
| Could this be split into 2+ independent commits? | Yes → request a split |
| Does the description mention everything the diff does? | No → incomplete description |
Leave a comment like: *"This refactor of `utils.py` looks unrelated to the login fix — can you split it into a separate PR so we can review the fix on its own?"*
## Guardrails
- **Never** bundle a big refactor into a small fix — it makes the fix unreviewable and unrevertible.
- **Never** silently add a dependency — new dependencies are a security, licensing, and maintenance decision.
- **Never** refuse *reasonable* adjacent fixes when the user clearly wants them — discipline isn't rigidity. If unsure, ask.
- **Always** flag out-of-scope findings in a list the user can approve or reject.
## Pitfalls
- **Bundling a big refactor into a small fix**: "While fixing the null pointer, I also rewrote the entire module." Now the reviewer can't tell what's the fix and what's the refactor — and reverting the fix reverts the refactor too.
- **Silently adding a dependency**: "I needed a date library so I added Moment.js." Unrequested deps bloat, introduce vulnerabilities, and should always be a separate, asked decision.
- **Refusing reasonable adjacent fixes and being unhelpful**: The opposite failure — the user asks you to fix a typo in a file and you refuse to also fix the immediately-adjacent broken import. Discipline means *flagging*, not *ignoring*.
- **Gold-plating**: Adding features, abstractions, and "future-proofing" nobody asked for. YAGNI — you aren't going to need it.
- **Scope creep through "small" additions**: Each individual addition seems tiny ("just one more field"), but they compound into a diff 10x the requested size.
## Verify / Checklist
- [ ] Every line in `git diff` traces to the stated requirement
- [ ] No new dependencies added without explicit approval
- [ ] No unrelated refactors, reformats, or bug fixes bundled in
- [ ] Out-of-scope findings listed separately (not silently made)
- [ ] Reversible/small/implied changes done and flagged; risky/opinionated/irreversible changes asked first
- [ ] Each logical change in its own commit, independently reviewable
- [ ] The diff size matches the task size (a "fix typo" task shouldn't produce a 500-line diff)
Attached files
No attached files.