Module 6: reframe Part C around the AI silently auto-resolving conflicts (#97)

A current frontier editor-agent told to "merge X into Y" resolves the
conflict and completes the merge in one turn, so the learner never sees a
marker. The old Part C assumed Git would stop and ask. Rework the lab into
a three-beat sequence: witness the conflict once (agent stop-on-conflict
idiom, as in Module 26), undo it with `git merge --abort`, then let the AI
merge for real and auto-resolve while the learner does the one job still
theirs: verify with `git diff` after every merge.

Updates the matching surfaces so they tell one story: learning objective
#4, the Merge-conflicts key concept, the AI-angle bullet, the
Where-it-breaks bullet, Check-for-understanding, the blog mirror, and the
make-conflict.sh on-screen guidance (read the markers yourself first).

Closes #97

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KCv6VTpBG6Zo4xR4AvUQpj
This commit is contained in:
2026-06-23 09:03:40 -04:00
parent 173f39ac44
commit 0f8e7497a4
3 changed files with 111 additions and 77 deletions
+16 -18
View File
@@ -121,7 +121,7 @@ That's it. Notice what you did *not* do: no file-by-file restore, no manual undo
This is the mental shift the module is selling. When discarding is *this* cheap, you stop being precious about what you let the AI try. Risky refactor? Branch it. Want to compare two approaches? A branch each; keep the winner, delete the loser. The branch becomes your unit of "maybe."
## Merge conflicts: when two changes collide (and the AI helps)
## Merge conflicts: when two changes collide (and the AI resolves them before you see them)
Most merges just work; Git is genuinely good at combining changes that touch *different* lines. A **conflict** only happens when two branches changed the *same* lines in different ways, and Git refuses to guess which you meant. It stops and marks the collision right inside the file:
@@ -135,27 +135,25 @@ Most merges just work; Git is genuinely good at combining changes that touch *di
Read it like this. Everything from `<<<<<<< HEAD` to `=======` is **your current branch's version**. Everything from `=======` to `>>>>>>> feature/stats` is **the incoming version**. The markers are real text Git inserted into your file. Resolving means editing the file so it holds the version you want (often a blend of both, here a usage string listing *both* commands) and deleting all three marker lines.
You can manufacture exactly this in `tasks-app`: make one branch where the AI adds a `stats` command (updating the usage string), then a *separate* branch off `main` where it adds a `purge` command (also updating the usage string). Both edit the same line. Merge one into the other and Git stops cold:
Here's the twist, and it's the reason I'm not going to hand you a "read the markers, edit them out" drill and call it a skill. You can manufacture exactly this collision in `tasks-app`: make one branch where the AI adds a `stats` command (updating the usage string), then a *separate* branch off `main` where it adds a `purge` command (also updating the usage string). Both edit the same line. Then tell a current editor-agent to "merge `feature/stats` into `feature/purge`," and watch what *doesn't* happen: it doesn't stop. It reads both sides, picks the resolution, finishes the merge, and reports a clean result, all in one turn. You never see a marker. From your chair the conflict simply didn't occur.
That's the sweet spot for the AI (a small, perfectly bounded reasoning task with both sides and the surrounding code right there) and it's also the trap. So do this once, deliberately, to see the machine: ask it to stop instead of resolving.
> *"Merge `feature/stats` into `feature/purge`. If it conflicts, stop and show me the conflict; don't resolve it yet."*
Now Git pauses on the unmerged file and you can read the markers above with your own eyes. Then `git merge --abort` to rewind, and let the agent do it for real with no guard rail, the way you actually would:
> *"Merge `feature/stats` into `feature/purge`; the usage line collides, and the final version should list BOTH commands."*
It resolves silently and the merge lands. And here is the only part that's still your job, conflict or no conflict:
```bash
git merge feature/stats
git status # cli.py listed under "Unmerged paths"
```
And here's where editor-integrated AI earns its keep, because a merge conflict is *the* sweet spot for it: a small, perfectly bounded reasoning task with both sides and the surrounding code right there. Ask:
> *"`cli.py` has a merge conflict on the usage line. I want the final version to list BOTH the `stats` and `purge` commands. Resolve the conflict and remove the markers."*
It should hand back a single marker-free line. Then you settle it with Git:
```bash
git diff # check ONLY what you intended changed; no markers remain
git diff HEAD~1 # what the merge actually changed; confirm no markers, both commands present
python cli.py # run it: see the merged usage string
git add cli.py
git commit # opens an editor for the merge message; save and close
python cli.py stats && python cli.py purge # both actually work
```
Once you can read those three lines of markers, conflicts stop being scary and become a five-minute chore. The syntax is identical no matter the file or the project. (And if your AI's edits didn't happen to collide (they're nondeterministic), the course ships a little `make-conflict.sh` helper that manufactures one deterministically so you can still practice.)
That `git diff` after *every* merge is the whole skill now. Not "edit the markers by hand," which the AI did for you before you could blink, but "know a conflict can happen and check the silent resolution," because a resolution that runs cleanly can still be wrong and it won't leave an error behind to warn you. (And if your AI's edits didn't happen to collide (they're nondeterministic), the course ships a little `make-conflict.sh` helper that manufactures one deterministically so you can still see the markers at least once.)
## The AI angle: why this matters *more* now
@@ -177,7 +175,7 @@ The honest limits, so you don't over-trust the sandbox:
## You're done when
You've created a branch, let the AI make a multi-file change on it, and confirmed `main` was untouched by switching back and watching the change vanish. You've **discarded** an experiment with `git branch -D` and seen `main` show no trace, and you've **merged** one in and seen it land. You can explain in one sentence why a branch costs essentially nothing (it's a movable pointer, not a copy). And you've read those `<<<<<<<` / `=======` / `>>>>>>>` markers, resolved a real conflict to a clean file that runs, and completed the merge.
You've created a branch, let the AI make a multi-file change on it, and confirmed `main` was untouched by switching back and watching the change vanish. You've **discarded** an experiment with `git branch -D` and seen `main` show no trace, and you've **merged** one in and seen it land. You can explain in one sentence why a branch costs essentially nothing (it's a movable pointer, not a copy). And you've seen those `<<<<<<<` / `=======` / `>>>>>>>` markers at least once, then watched the AI merge for real and resolve the conflict silently, and you verified the result with `git diff` even though no marker was ever shown to you.
When "let the agent try something wild" feels like a one-line decision instead of a risk assessment, you've got it.