Lesson 3: The bounded change, reviewed turn by turn
Objective
The starter passes all nine tests through a sequence of bounded changes,
and you can explain every diff the agent produced without reading the
solution first.
Why this lesson exists
This is the lesson people skip — and the one that builds the actual skill.
Letting the agent rewrite the file in one shot teaches you nothing and
gives you a diff you cannot honestly review. Supervising small diffs, each
pinned to a contract line, is how the code stays yours.
Copilot adds one thing you must know: in a Copilot (Agent Host) session the
agent applies and saves edits directly. Manual permissions makes commands
and tool calls wait for you; it does not hold file edits for approval. So
the boundary is not an “accept” button — it is the review you do after
each turn, before you send the next prompt.
Set up the safety net (once)
-
A Git baseline. If the working folder is not a Git repository yet,
run git init, then git add -A and git commit -m "baseline". The
Source Control view now shows exactly what each turn changed.
-
Per-request change summaries. In Settings, turn on
chat.checkpoints.showFileChanges. Each completed request then lists
the files it changed with line counts, and View All File Changes
opens a multi-file diff.
-
(Optional) Ask before touching read-only files. The
chat.tools.edits.autoApprove setting takes glob patterns; files set
to false show a diff and wait for your approval before the edit is
applied. Put this in .vscode/settings.json:
{
"chat.tools.edits.autoApprove": {
"**/*": true,
"**/tests/**": false,
"**/solution/**": false,
"**/scenario/**": false
}
}
The lesson
Start a fresh chat session (a finished task’s chat carries stale context),
keep the Agent role and Manual permissions, and say:
“Work through TASK.md against starter/report_tool.py. One failing test
group at a time: JSON loading, then validation isolation, then rounding,
then atomic writes, then the end-to-end tests. After each group, run
python verify.py starter, then stop and wait for me before the next
group.”
After every turn, before you reply:
- Open the turn’s changed files (or Source Control) and read every hunk.
Only
starter/report_tool.py should have changed. If anything in
tests/, solution/, or scenario/ moved, hover over that request and
select Restore Checkpoint, then ask why.
- No new imports outside the standard library — and no import that is not
needed by the change being made.
- Each change should move toward one contract line. Reject drive-by
refactors (“while I was here I renamed…”) by restoring the checkpoint and
re-asking with a narrower prompt.
- If the agent wants to change a test, the answer is no. Tests are the
contract; the code moves.
- When a group is green and the diff makes sense, commit it in Source
Control. That commit is your permanent record; checkpoints are temporary.
Read every command approval request too: python verify.py starter is
safe; pip install anything is a stop sign. Restore Checkpoint rolls back
files and chat history, but it does not reverse a command that already
ran — which is why commands are the thing Manual permissions holds for you.
Expect the failing count to drop group by group: 7 → 5 → 4 → 3 → 2 → 0.
Exercise
Pick one hunk the agent produced — ideally the validation-isolation
change — and explain it back in the chat: “line N does X; that satisfies
contract line Y.” If you cannot, ask the agent to walk you through its own
diff before sending the next group.
Checkpoint
Run python verify.py. This checkpoint’s code appears only when
the starter suite is green. You pass the lesson when you can answer:
- How many turns did the bounded change take, and what made each turn
bounded?
- Which diff or command did you roll back or narrow, and how — checkpoint,
denied approval, or a narrower prompt?
- Point at the hunk that implements “isolate invalid rows with reasons” —
where is it?
Expected evidence
A green python verify.py starter run, your per-group commits, and your
hunk-by-hunk explanation of the change that earned them.