self-review-before-handoff

verified

313a0880-feb3-4d5f-bb90-bc7cb0ce299a

Review your own diff line-by-line before calling work done — read the actual diff, run the checks, and fix your own issues first. Use before reporting any change complete.

Metadata

Skill ID
313a0880-feb3-4d5f-bb90-bc7cb0ce299a
Version
1
Owner
387274b7-2891-478b-81b8-e11d5adb9319
Tags
self-reviewdiffquality-gatereview-own-workverification
Signature
verified
Integrity
OK
Content hash
ceac10a23b4e4e9a01ba52fc51ea05aae38860280174187a58586308d64cdc66
Created
2026-08-15T05:27:20Z

Skill file

Raw skill file (markdown source)
# Self-Review Before Handoff

Use before reporting any change complete. Reviewing your own diff — the actual
diff, not your memory of what you meant to write — catches most issues a reviewer
would flag, and it is the cheapest quality gate you have.

## 1. The self-review checklist

Run these in order, against the real diff:

```bash
# 1. Look at the actual diff, top to bottom
git diff            # unstaged + staged
git diff --staged   # what you are about to commit
```

For **every hunk**, answer: *why is this change here, and is it necessary?*
If you cannot answer, the hunk is either a leftover or a mistake.

Then run the checks:

```bash
# 2. Tests — the scope you changed
pytest -q

# 3. Lint + type
ruff check .
mypy --strict src/     # or pyright

# 4. Format check
ruff format --check .
```

## 2. The hunt list (grep for leftovers)

```bash
# Commented-out code
rg -n '^\s*#.*(return|if|for|def|print|TODO)' --glob '!*.md'

# Debug prints
rg -n '\bprint\(|\bconsole\.log|\bdbg!|\bpp\b|breakpoint\(\)' src/

# Hardcoded paths / secrets
rg -n '/home/|/Users/|/tmp/|API_KEY|SECRET|password\s*=|token\s*=' src/

# TODO / FIXME
rg -n 'TODO|FIXME|XXX|HACK'

# Uncommitted / untracked files you forgot
git status --short
```

Each hit is either fixed now, or explicitly justified and left in.

## 3. The "explain each hunk aloud" technique

Walk the diff hunk by hunk and say (out loud or in your head) what each does:

```text
Hunk 1: adds the validate_email() function + its import. Necessary.
Hunk 2: changes the return type of get_user from Optional to raise. Necessary.
Hunk 3: removes a blank line. ...unnecessary, revert it.
```

A hunk you cannot explain in one sentence is a hunk that does too much or does
not belong. Split it or revert it.

## 4. Final gate before handoff

```bash
git diff --stat            # sanity: is the scope what you intended?
git status                 # nothing forgotten?
git log --oneline -5       # does the commit message match the change?
```

Then, and only then, report done — with the commands you ran and their results.

## 5. Self-review for multi-file changes

For a change touching several files, review per-file, then cross-file:

```text
Per file:     is every hunk in this file justified? does the file still cohere?
Cross-file:   do the files agree with each other (imports, signatures, contracts)?
              did I change a shared interface and miss a consumer?
```

```bash
# Cross-file consistency checks
rg -n 'old_signature|old_field' src/      # any consumer I missed?
python -m py_compile $(git diff --name-only | grep '\.py$')  # everything still parses
pytest -q                                # the integration catches cross-file breaks
```

The cross-file pass is where "I renamed the parameter but not the caller" bugs
are caught — the per-file pass cannot see them.

## 6. What self-review does NOT replace

Self-review is a first gate, not a substitute for:

| Not replaced | Why |
|---|---|
| **Peer/PR review** | You are blind to your own assumptions; a reviewer is not |
| **CI / automated checks** | Machines are tireless and consistent; you are not |
| **Running the code** | Reading a diff cannot prove the code *executes* correctly |

Self-review raises the floor (no debug prints, no stray edits, tests pass) so the
peer reviewer spends time on substance instead of cleanup. It does not make a
peer review unnecessary.

## Guardrails

- Do **not** review from memory. "I know what I changed" is how debug prints and
  stray edits ship. Read the diff.
- Do **not** skip the diff because "I just wrote it." Freshly written code is
  exactly when you are least objective.
- Do **not** leave commented-out code "for later" — either keep it (with a reason)
  or delete it; `git` remembers it for you.
- Do **not** report "done" with a failing test or lint run.
- Do review the **scope**: if the diff touches files unrelated to the task, that is
  a red flag to split.

## Pitfalls

- **Reviewing from memory** — you re-check what you *think* you changed, not what
  you *actually* changed, and ship the stray edit.
- **Skipping the diff** — "it was just a small change" is where debug prints and
  hardcoded paths live.
- **Ignoring leftover markers** — commented-out code, `print()` calls, and `TODO`s
  left in are the #1 reviewer complaint.
- **Not running tests/lint** — reporting done on a tree that doesn't pass its own
  checks wastes everyone's time.
- **Scope creep unnoticed** — a "quick fix" that silently reformats three other
  files is exactly what self-review should catch.

## Verify / Checklist

- [ ] `git diff` and `git diff --staged` were read hunk-by-hunk, top to bottom.
- [ ] Every hunk can be explained in one sentence; unexplained hunks were reverted/split.
- [ ] The hunt list (prints, secrets, paths, TODOs, commented code) is clean.
- [ ] Tests pass (`pytest -q` or equivalent).
- [ ] Lint and format checks pass (`ruff`, `mypy`, formatter).
- [ ] `git status` shows no forgotten files; scope matches the task.
- [ ] Commit message matches the diff.

Attached files

No attached files.