← All writing
Singy Songbook · 6 of 12
May 20, 2026 · 5 min read

Scope Discipline: One 12-Item Request, Three Focused PRs

Tuesday morning. I'd been using SingWithMe2 for a few days and had a list of small things to change. Pasted twelve items into Claude:

  • Bold the character counts on song cards.
  • Keyboard shortcuts on the flashcards (space to reveal a hint).
  • Per-song mastery score.
  • Study mode that cycles through unmastered lines.
  • Move the sound on/off toggle into a settings screen.
  • Slow the text-to-speech rate.
  • (...etc)

I expected one big PR.

What came back was a proposal to split:

Batch A (display + keyboard): UI tweaks and shortcuts. UI-only, no DB changes, no new endpoints. Low risk, easy to review.

Batch B (mastery tracking): per-song mastery score, plus a backfill so songs already practiced show the right number. New table, migration, backfill logic. Higher risk but self-contained.

Batch C (Study mode + settings): deck cycling, completion animation, settings page, sound toggle. Sits on top of Batch B's data, so landing B first keeps C cleaner.

Three PRs, in order. Reviewable one at a time. Sound right?

Yes.

Why splitting matters

Bundling twelve changes into one PR feels efficient. It isn't:

  • Review attention is a flat resource. Either you skim (and miss the risky change) or you read carefully (and burn 40 minutes on changes that couldn't break anything). Mixed-risk PRs make the wrong attention level rational either way.
  • Any one change blocks the others. If the migration needs rework, the bold-font edit sits in limbo.
  • When something breaks in production, you don't know which change caused it. Twelve new things just shipped; all you know is something broke.

Three focused PRs fixed each of those. Batch A reviewed in five minutes because nothing in it could break. Batch B reviewed carefully because I cared about not corrupting practice history. Batch C reviewed with an eye on the product because the plumbing was already in place.

The ordering wasn't arbitrary

Claude sequenced these on purpose:

  • Easy batch first as a confidence check. If something weird happened with the deploy pipeline, we'd find out on a low-risk PR.
  • Database change second so the Study mode work could use the mastery data. Otherwise Batch C would need temporary scaffolding, which would then need ripping out — churn and risk.
  • Biggest product batch last so it could be shaped by what I saw in the first two. Once the mastery UI was live, I had ideas about the Study mode completion animation I wouldn't have had while staring at a spec.

The third reason is the one I'd have missed on my own. By splitting, I got two rounds of feedback into my planning before committing to the hardest piece.

The move I'm keeping

When the list has more than a few items, ask for a batching plan before any code gets written. Push on the plan until I like it. Then let one batch execute.

Costs an extra turn at the top. Saves an hour of PR review and several hours of "which of those twelve changes broke the thing."

What landed

Three PRs shipped over about a day. Batch A: ~20 minutes end-to-end. Batch B: longest, because the migration had to preserve history from existing attempts. Batch C: most fun to review because the foundation was solid and I was reviewing product, not plumbing.

Smaller PRs being better than big ones isn't an AI lesson — it's just an old PR-review lesson. The AI is fast enough that the cost of scoping becomes salient in a way it wasn't when the same call happened between humans across days.

Takeaways

  • Bundling unequal-risk changes makes review attention miscalibrate either way (skim and miss the risky one; read carefully and burn time on the safe ones).
  • Sequence batches by risk and dependency. Easy first as a pipeline check; database changes in the middle; biggest product batch last so it can be shaped by what you saw.
  • When the request has more than a few items, ask for a batching plan before any code gets written. One extra turn at the top saves hours of review and rollback ambiguity.

Terms

Pull request (PR) — A proposed batch of code changes. On GitHub, opening one creates a review surface — a list of what changed, comments, and a Merge button.

Migration — A script that changes the database schema (adds a table, adds a column, etc). Run when the app deploys so the running code matches the database shape.

Backfill — A one-time data fix that runs after a migration to populate the new column or table for existing rows. For example: if you add a mastery_score column to a table of songs that already have practice history, the backfill computes the score for each existing row from that history.

Endpoint — A URL the backend handles. POST /api/songs is one endpoint, GET /api/songs/{id} is another.

Deploy pipeline — The chain of automated steps that takes a git commit and turns it into a running, accessible service. For this project: push to GitHub → Vercel rebuilds the frontend → Fly redeploys the backend.

Scaffolding (temporary) — Code written to fill a gap that's expected to be removed later. If Batch C had landed before Batch B, it would have needed a fake mastery score to render against; that fake would then have to be torn out when the real data arrived.