A four-line patch, two approvals, and a retry that never fires
A small project ships a four-line change to an error-handling branch late on a Friday afternoon. Two reviewers read the diff, both approve it, and the patch merges with a green CI run. Three weeks later a downstream consumer reports a retry loop that never fires, and the root cause sits in a caller nobody re-read. That story is a composite illustration rather than a logged incident, but it captures a real tension in small-maintainer projects: review attention is scarce and the diff is the only surface anyone inspects.
Whole-repository review prompts do not fix this, because they spend effort rescanning untouched code. Pure hunk-level prompts fail in the opposite direction, because a diff without its consumers hides every caller that depends on the changed behavior. What a maintainer actually needs is a compact, per-symbol artifact that lists the blast radius of each change and the commands that could falsify the author's claims.
Why per-symbol packets beat whole-repo prompts
- A repository-scale prompt forces a model to restate imports, configs, and unrelated modules instead of testing the change under review.
- A hunk-only prompt omits call sites, so a signature change looks harmless until a downstream branch dereferences a now-nullable value.
- Neither format yields something executable, so approvals end up resting on prose instead of on observable checks with exit codes.
- Small maintainer teams rarely have a second human reviewer available, which is exactly where a cheap breadth pass earns its place.
The workflow below is a proposal, and the scripts are unexecuted sketches meant to be adapted. It produces one ledger row per changed symbol, each row carrying its call sites, its referencing tests, and a small packet that a free model can review in isolation. Substitute your own build commands wherever make test appears.
Step 1 — Freeze a reproduction receipt first
No review should start before the base commit and the current test state are recorded in a single file. The receipt removes the most common argument in OSS threads, which is whether the failure even exists on the author's machine. Keep the log hash so a later rerun can prove the environment changed rather than the code.
set -euo pipefail
mkdir -p .review
BASE=$(git merge-base origin/main HEAD)
{
echo "base=$BASE"
git rev-parse HEAD
python3 --version
git --version
} > .review/receipt.txt
make test > .review/baseline.log 2>&1 || echo "exit=$?" >> .review/baseline.log
sha256sum .review/baseline.log >> .review/receipt.txt
Step 2 — Derive the blast radius from hunk headers
Git already knows which function each hunk belongs to, and -U0 keeps the output small enough to parse. The hunk header after the second @@ carries the enclosing function or class context, which is precisely the symbol under review. Inspect it manually before automating anything.
git diff -U0 "$BASE"...HEAD | grep -E '^@@' | head -n 40
Each matching line becomes one ledger row, and each row gets its own call-site search. The search is deliberately textual and dumb, because a call-graph tool that fails to resolve dynamic dispatch produces false confidence. Filter vendored directories, then confirm every surviving hit by reading it.
Step 3 — Emit one ledger row per changed symbol
The script below reads the hunk headers and writes a Markdown table with candidate call sites. It is intentionally short enough to audit in a review, since a 400-line helper script becomes its own maintenance burden.
# ledger.py — proposal, not executed in this article
import re, subprocess
def sh(*args):
return subprocess.run(args, capture_output=True, text=True, check=True).stdout
def symbols(base):
diff = sh('git', 'diff', '-U0', f'{base}...HEAD')
rows = []
for line in diff.splitlines():
m = re.match(r'^@@ .* @@\s*(.+)$', line)
if not m:
continue
ctx = m.group(1).strip()
name = re.split(r'[(\s:]', ctx)[0]
if re.fullmatch(r'[A-Za-z_][A-Za-z0-9_]*', name or ''):
rows.append(name)
return sorted(set(rows))
def call_sites(name):
hits = sh('git', 'grep', '-n', '--', name).splitlines()
return [h for h in hits if '/vendor/' not in h]
base = sh('git', 'merge-base', 'origin/main', 'HEAD').strip()
for name in symbols(base):
hits = call_sites(name)
print(f'| `{name}` | {len(hits)} | ' + '<br>'.join(h.split(':')[0] for h in hits[:6]) + ' |')
Step 4 — Use a free-model breadth pass on each packet
A packet per symbol stays small, so a free model can read several of them without being asked to hold the whole repository in context. MonkeyCode is relevant at this step for two operator-supplied reasons: it offers free model access and a free server option, which lowers the cost of running breadth passes over many small packets. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Specific quotas, hardware, and duration are not verified here, so confirm the current terms on the project's own pages before depending on them.
The prompt below asks for claims, checks, and unknowns rather than a verdict, because a model's approval carries no accountability. Keep the packet to the hunk, the symbol name, the call sites, and the tests that mention the symbol.
You are reviewing one changed function, not a repository.
Inputs: symbol name, unified diff hunk, direct call sites, tests referencing the symbol.
Output exactly three sections:
1. CLAIMS — behaviors this change could alter, one per line.
2. CHECKS — one shell command per claim that would prove it false.
3. UNKNOWNS — invariants you cannot verify from this packet.
Do not restate the diff. Do not praise. Do not approve.
Step 5 — Falsify every claim before anyone approves
The value of the packet is that each CLAIMS line maps to a command a maintainer can actually run, so the review ends with evidence instead of adjectives. Record verdicts in the PR description, and mark anything unverifiable as an explicit unknown rather than a silent pass. The rows below are illustrative placeholders, not output from a real run.
| Claim from packet | Check command | Verdict | Action |
|---|---|---|---|
| Retry branch is still reachable | go test ./client -run TestRetry -count=1 |
pass | keep |
| Caller assumes a non-nil return | git grep -n 'fetchConfig(' -- '*.go' |
3 hits, 2 unchecked | add guard or note in PR |
| New timeout changes default behavior | git grep -n 'defaultTimeout' |
4 configs, none tested | flag as unknown |
The falsification loop is short enough to run by hand, and that is a feature rather than a limitation. Automating it too early hides disagreements about what a check actually proves.
while IFS= read -r cmd; do
printf '>>> %s\n' "$cmd"
bash -c "$cmd" && echo 'PASS' || echo 'FAIL'
done < .review/checks.txt
When a free-model breadth pass is worth the tokens
| Change shape | Breadth pass | Human depth pass | Reason |
|---|---|---|---|
| Mechanical rename across many files | yes | spot-check | errors are local and greppable |
| Auth branch or crypto constant | no as sole reviewer | required | accountability cannot be delegated |
| Error message or log text | yes | skip | low blast radius |
| Concurrency primitive or lock ordering | yes for hypotheses | required | runtime invariants are invisible in diffs |
| Docs, comments, license headers | skip | lint instead | mechanical tooling is cheaper |
The table is a starting point rather than a policy, and each row should be re-argued when the repository's test suite changes. Teams that cannot name a command for a claim should treat that claim as an unknown.
Limitations and who should skip this
- A model cannot run the suite, so any claim about runtime behavior stays a hypothesis until a command settles it.
- Textual call-site search misses reflection, generated code, and dynamic dispatch, which inflates confidence in languages that rely on them.
- Free-tier availability and capacity can change without notice, so a workflow that hard-depends on it needs a fallback path.
- Proprietary or license-restricted code should not be pasted into any hosted endpoint until data handling is confirmed by the operator.
- Security-critical patches still need an accountable human reviewer, and model output should never be recorded as an approval.
The ledger adds overhead on trivial patches, and a two-line documentation fix does not justify it. It pays off when a change touches shared symbols, when reviewers are scarce, or when a previous patch merged cleanly and still broke a consumer.
If the per-symbol ledger fits an existing maintainer workflow, check the project's current documentation for the free access and server terms before adopting it, and keep the fallback path written down.
What to keep after the patch merges
Archive the receipt, the ledger table, and the falsification log next to the pull request link, because the next bug report will reference one of them. A three-file record answers the questions that usually reopen a dead thread: what was tested, on which base commit, and which claim was never verified. That archive is cheap to keep and far more useful than a review thread nobody can reconstruct.
Top comments (0)