fix(M1-6): apply AI-drives-git reframe, lesson=theory, de-slop, + issue fixes

Phase 1 of the reframe. M1-3 stay manual-by-hand (browser chat); M4 is the pivot
to the AI agent (Claude Code as example); M5-6 are agent-driven.

- M1: de-slop (em-dashes), relocate the build-note out of the lab. Seam devices kept.
- M2: #78 tell learner how to paste cli.py into chat; #79 commit the delete so the
  tree ends clean. restore/cold-session devices kept.
- M3: #80 define ADR; #81 create-file-before-add; #82 ls before/after merge to prove
  branch isolation; #83 drop "prose"; M3 now owns the branch-basics intro.
- M4: #84 Claude Code as the worked example; #85 AI drives git (arithmetic->calculator);
  #86 /path/to -> ~/ai-workflow-course; #87 agent does the revert+verify.
- M5: #88 ask the agent which config files to commit, then let it stage/commit
  (CLAUDE.md example; repo still uses AGENTS.md).
- M6: #90 stop re-teaching branch basics; rescope to the AI experimenting on a branch;
  the engineered conflict is now AI-resolved, learner-verified.

Closes #78
Closes #79
Closes #80
Closes #81
Closes #82
Closes #84
Closes #85
Closes #87
Closes #88
Closes #90

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TfzV5QvtPDz8LJS3Pu5VLT
This commit is contained in:
2026-06-22 21:41:14 -04:00
parent 2467f25901
commit 896c4606c6
8 changed files with 578 additions and 481 deletions
+76 -59
View File
@@ -1,8 +1,8 @@
# Module 3 — Version Control for Words, Not Just Code
> **The safest possible place to practice Git is on prose — and it happens to be a genuinely useful
> skill on its own.** Branch an ADR, let the AI draft it, read the diff, merge it. Nothing breaks if
> it's wrong, so you build the muscle before the agent ever touches code.
> **The safest place to practice Git is on words, and it happens to be a genuinely useful skill on
> its own.** Branch an Architecture Decision Record (ADR), let the AI draft it, read the diff, merge
> it. Nothing breaks if it's wrong, so you build the muscle before the agent ever touches code.
---
@@ -25,12 +25,12 @@ is exactly the low-risk on-ramp that makes the copy-paste friction tolerable one
By the end of this module you can:
1. Explain why plain-text formats (markdown, AsciiDoc) version cleanly while `.docx`/`.pptx` version
uselessly and make the case to move a runbook or ADR out of Word.
2. Create a branch, do work on it, and merge it back the full branch → diff → commit → merge loop —
on a document where a mistake costs nothing.
uselessly, and make the case to move a runbook or ADR out of Word.
2. Create a branch, do work on it, and merge it back. That's the full branch → diff → commit → merge
loop, run on a document where a mistake costs nothing.
3. Have an AI draft a real engineering document (an ADR or a runbook) and review its work as a diff
before accepting it.
4. Recognize that the wikis on most Git hosts are themselves Git repositories so the docs you
4. Recognize that the wikis on most Git hosts are themselves Git repositories, so the docs you
thought lived "in a web UI" were version-controlled all along.
---
@@ -57,7 +57,7 @@ format Git can actually work with. That "if" is the whole argument.
### Why plain text wins: the diff is line-based
Git's core operation is the line-based diff. It compares two snapshots and reports which **lines**
changed. Everything good about Git readable history, reviewable changes, automatic merges is
changed. Everything good about Git (readable history, reviewable changes, automatic merges) is
built on that one capability. So a format versions well in exact proportion to how well it maps onto
*lines of text*.
@@ -90,7 +90,7 @@ This is a real, defensible engineering argument, not a style preference:
> drive.** The moment a document needs history, review, or more than one author, a binary format is
> actively costing you the thing version control exists to provide.
The honest counterpoint where binary formats still earn their place is in *Where it breaks*.
The honest counterpoint, where binary formats still earn their place, is in *Where it breaks*.
### The document types worth versioning
@@ -107,9 +107,9 @@ You don't need to convert everything. These are the high-value targets, all natu
- **Changelogs** — what changed in each release. A markdown `CHANGELOG.md` is the standard.
- **Specs / PRDs** — what you're going to build and why, before you build it.
For this audience the ADR is the gateway drug: small, structured, high-value, and the kind of thing
that *never* gets written because it feels like overhead right up until the AI will draft it for
you in ten seconds.
For this audience the ADR is the easiest win: small, structured, high-value, and the kind of thing
that *never* gets written because it feels like overhead, right up until the AI drafts it for you in
ten seconds.
### Branch → diff → commit → merge (the new verbs)
@@ -117,19 +117,21 @@ Module 2 worked on a straight line of commits. A **branch** is a second line you
disturbing the first. The mental model: `main` is the version everyone trusts; a branch is a private
copy where you draft something, and **merge** folds your finished work back into `main`.
For a document, the loop is:
Creating a branch is one command, and `git branch` shows you which line you're on:
```bash
git switch -c docs/adr-storage # create a branch and switch to it
# ...write the doc, with the AI's help...
git add docs/adr/0001-storage.md
git diff --staged # review exactly what's going onto the branch
git commit -m "Add ADR 0001: store tasks as JSON"
git switch main # back to the trusted version
git merge docs/adr-storage # fold the finished doc into main
git branch -d docs/adr-storage # delete the branch; its work is now in main
```console
$ git switch -c docs/adr-storage
Switched to a new branch 'docs/adr-storage'
$ git branch
* docs/adr-storage
main
```
The `*` marks your current branch. From there, the loop for a document is the same handful of verbs
every time: **draft** the doc (with the AI's help), **stage** it, read the **diff**, **commit** it on
the branch, **switch** back to `main`, then **merge** to fold the finished work in and delete the
spent branch. You'll run that whole sequence by hand in the lab; here, just hold the shape.
Two new-command notes for this audience:
- **`git switch -c <name>`** creates and moves onto a branch. (Older docs and muscle memory use
@@ -143,13 +145,13 @@ Two new-command notes for this audience:
Because this is one document on its own branch, the merge is trivial: nothing else touched `main`
while you worked, so Git **fast-forwards** — it just slides `main` up to your branch with no
conflict. That clean case is the whole reason we practice here first. What happens when two branches
edit the *same lines* a merge conflict is a real skill, and it gets its own treatment in
edit the *same lines* (a merge conflict) is a real skill, and it gets its own treatment in
**Module 6**, on code, where the stakes make it worth the depth. Practice the happy path now; the
hard path is easier once the verbs are reflexes.
### The aha: your wiki was a Git repo all along
Most Git hosts GitHub, GitLab, Gitea, and others ship a **wiki** alongside each repository. It
Most Git hosts (GitHub, GitLab, Gitea, and others) ship a **wiki** alongside each repository. It
looks like a web app: you click "New Page," type in a box, hit save. It feels like a different kind
of thing from your code.
@@ -159,9 +161,9 @@ Every page is a `.md` file. Every "save" in the web UI is a commit. The web edit
convenience layer over `git commit`.
The consequence: the documentation you've been editing in a browser textbox has had full version
history diffs, blame, the works the entire time. You can clone it, edit the markdown locally with
history (diffs, blame, the works) the entire time. You can clone it, edit the markdown locally with
the same branch/diff/merge loop you're learning here, and push it back. (Cloning and pushing to a
remote repo is **Module 8** remotes and hosting so you can't do the clone in *this* lab yet. But
remote repo is **Module 8** (remotes and hosting), so you can't do the clone in *this* lab yet. But
the realization changes how you see every wiki you'll ever touch: it's not a CMS, it's a repo
wearing a web UI.)
@@ -175,16 +177,16 @@ Here's why this module is more than "learn Git on easy mode":
models have — they were trained on oceans of it, and they reach for it by default. Asking an AI to
"write an ADR for this decision" or "turn these rough notes into a runbook" plays directly to its
strengths. The output is genuinely good and genuinely in the right format, with zero conversion.
- **"Draft it, branch it, diff it, merge it" is adoptable tomorrow.** You don't need new tools, a new
model, or editor integration. The exact workflow branch, paste the AI's draft into a `.md` file,
read the diff, merge — works today with the browser chat you already have open. Most of the rest of
this course unlocks capability you have to build up to. This one you can use on Monday.
- **Prose diffs are how you review AI writing.** Same skill as reviewing AI code (Module 10), lower
- **"Draft it, branch it, diff it, merge it" works today.** You don't need new tools, a new model, or
editor integration. The whole workflow (branch, paste the AI's draft into a `.md` file, read the
diff, merge) runs on the browser chat you already have open. Most of the rest of this course is
capability you have to build up to; this part you can put to work right now.
- **Reading the diff is how you review AI writing.** Same skill as reviewing AI code (Module 10), lower
stakes. The AI will write an ADR that *sounds* authoritative and confidently states a rationale it
invented. Reading the diff is how you catch "wait, that's not why we did this." The format makes the
review possible; your judgment makes it correct.
- **It seeds a habit the whole course depends on.** Once "the AI drafts, I review the diff, I decide"
is reflexive on documents where a mistake costs nothing you'll apply it without thinking when
is reflexive on documents, where a mistake costs nothing, you'll apply it without thinking when
the AI starts editing code, opening PRs, and running unattended later on.
---
@@ -222,28 +224,35 @@ zero.
### Part B — Let the AI draft the ADR
2. Make a home for decision records and copy in the template:
2. Make a home for decision records:
```bash
mkdir -p docs/adr
# copy modules/03-version-control-for-words/lab/adr-template.md
# to docs/adr/0001-task-storage-format.md
```
3. In your browser chat, give the AI the context and the template, and ask for the draft. Something
like:
3. Open `adr-template.md` from this module's `lab/` folder in the course repo (wherever you downloaded
it; it lives in the course repo, *not* inside `tasks-app`). In your browser chat, give the AI that
template plus the context and ask for the draft:
> *"Here's an ADR template (paste `adr-template.md`). Fill it out for this decision: the `tasks-app`
> CLI stores its state in a plain `tasks.json` file next to the code. We chose JSON over SQLite or
> a hosted database because the app is a single-user local tool and zero-setup matters more than
> query power. Keep it concise. Output markdown."*
> *"Here's an ADR template (paste the contents of `adr-template.md`). Fill it out for this decision:
> the `tasks-app` CLI stores its state in a plain `tasks.json` file next to the code. We chose JSON
> over SQLite or a hosted database because the app is a single-user local tool and zero-setup
> matters more than query power. Keep it concise. Output markdown."*
Paste the result into `docs/adr/0001-task-storage-format.md`, replacing the template body. (This is
the copy-paste loop from Module 1 — last stretch before Module 4 removes it.)
4. Now create the file and paste the draft in. In your editor, make a new file at this exact path
inside `tasks-app`:
```
docs/adr/0001-task-storage-format.md
```
Paste the AI's markdown into it and save. (This is the copy-paste loop from Module 1, the last
stretch before Module 4 removes it.) The file has to exist on disk before the next part can stage
it.
### Part C — Review the diff before you accept it
4. A brand-new file is untracked, so `git diff` shows nothing yet. Stage it, then review:
5. A brand-new file is untracked, so `git diff` shows nothing yet. Stage it, then review:
```bash
git status # the new file shows as "untracked"
@@ -251,12 +260,12 @@ zero.
git diff --staged # every line of the new doc, as additions
```
**Read it.** This is the point of the whole module: don't accept AI prose you haven't read. Check
the *substance*, not just that it's well-formatted — did it state a rationale you actually agree
with, or did it invent a confident-sounding reason? If it's wrong, edit the file and
`git add` again.
**Read it.** This is the point of the whole module: don't accept AI writing you haven't read. Check
the *substance*, not just that it's well-formatted. Did it state a rationale you actually agree
with, or did it invent a confident-sounding reason? If it's wrong, edit the file and `git add`
again.
5. When it's right, commit it on the branch:
6. When it's right, commit it on the branch:
```bash
git commit -m "Add ADR 0001: store tasks as JSON"
@@ -265,7 +274,7 @@ zero.
### Part D — Make a one-line edit and see the line-based diff
6. Edit one sentence in the ADR tighten a line, fix a claim, whatever. Save, then:
7. Edit one sentence in the ADR (tighten a line, fix a claim, whatever). Save, then:
```bash
git diff
@@ -281,17 +290,25 @@ zero.
### Part E — Merge it into main
7. Switch back to `main` and fold in the finished document:
8. First, switch back to `main` and prove the document isn't there yet. You created the whole
`docs/adr/` directory on the branch, so on `main` it doesn't exist:
```bash
git switch main
git log --oneline # note: your ADR commits aren't here yet
git merge docs/adr-storage # fast-forward — no conflict
git log --oneline # now they are
ls docs/adr/ # the ADR is on main
ls docs/adr/ # error: "No such file or directory" — it's only on the branch
git log --oneline # and your ADR commits aren't here either
```
8. Clean up the branch — its work now lives in `main`:
That's branch isolation: the work is real and committed, but completely invisible to `main` until
you merge. Now fold it in and watch the file appear:
```bash
git merge docs/adr-storage # fast-forward, no conflict
git log --oneline # the ADR commits are on main now
ls docs/adr/ # and the file is here too
```
9. Clean up the branch. Its work now lives in `main`:
```bash
git branch -d docs/adr-storage
@@ -303,9 +320,9 @@ doing the writing and you doing the reviewing. That's the loop the rest of the c
### Optional — do it again as a runbook
Repeat the loop on a different branch (`git switch -c docs/runbook-restore`) using
`lab/runbook-template.md`: ask the AI to write a runbook for "restore the tasks list after someone
deletes `tasks.json` by accident" given that the app recreates an empty list on next run. Same five
parts. Doing it twice is what turns the commands into reflexes.
`runbook-template.md` from this module's `lab/` folder: ask the AI to write a runbook for "restore the
tasks list after someone deletes `tasks.json` by accident," given that the app recreates an empty list
on next run. Same five parts. Doing it twice is what turns the commands into reflexes.
---