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:
@@ -30,7 +30,7 @@ By the end of this module you can:
|
||||
2. Install, authenticate, and point one of them at a real repository, then confirm it can actually
|
||||
read the project.
|
||||
3. Run the agentic edit → review → iterate loop: let the AI change real files, read the change as a
|
||||
`git diff`, and either keep it or revert it.
|
||||
`git diff`, and direct the AI to keep it (commit) or revert it.
|
||||
4. Set the tool's permissions deliberately — what it may read, edit, and execute without asking.
|
||||
5. Explain precisely why this is safe, in terms of Module 2's `restore`.
|
||||
|
||||
@@ -41,10 +41,10 @@ By the end of this module you can:
|
||||
### What "out of the browser" actually means
|
||||
|
||||
In the browser-chat loop, the AI is blindfolded and handcuffed. It can't see your files unless you
|
||||
paste them in, and it can't change them — it can only hand you text to copy back. *You* are the
|
||||
paste them in, and it can't change them; it can only hand you text to copy back. *You* are the
|
||||
integration layer: you decide which files it sees, you apply its output, you are the one who notices
|
||||
it forgot to update the second file. That's seam 1 from Module 1, and no smarter model fixes it,
|
||||
because it isn't an intelligence problem — it's an *access* problem.
|
||||
because it isn't an intelligence problem, it's an *access* problem.
|
||||
|
||||
Getting the AI out of the browser means giving it two things it never had in the chat tab:
|
||||
|
||||
@@ -57,6 +57,24 @@ Everything in this module follows from those two capabilities. They're also exac
|
||||
to come first: write access to your files is only acceptable when every edit is visible and
|
||||
reversible.
|
||||
|
||||
### From here on, the AI drives git
|
||||
|
||||
Modules 1–3 had you type git by hand — `commit`, `branch`, `diff`, `restore` — on purpose. The AI
|
||||
was stuck in the browser and couldn't touch your repo, so you built the muscle yourself. That was
|
||||
learning arithmetic by hand before you're handed a calculator.
|
||||
|
||||
This module hands you the calculator. Once an agent runs inside your repo it can run commands too,
|
||||
git included, so the work splits cleanly:
|
||||
|
||||
- **You describe the change** and **review the diff** it produces.
|
||||
- **The AI edits the files and runs git** — it stages, commits, and reverts.
|
||||
- **You verify the result**: the diff is what you asked for, the checkpoint landed, the tree is clean.
|
||||
|
||||
You don't stop understanding git; you stop typing it. The concepts from Modules 2–3 are exactly what
|
||||
let you check the AI did the right thing. From this module on the course assumes this split: when a
|
||||
step needs a commit or a revert, you tell the agent and verify its work instead of reaching for the
|
||||
keyboard. The one thing that stays in your hands is reading the diff.
|
||||
|
||||
### The two categories
|
||||
|
||||
There are two shapes this tooling comes in. They overlap, and plenty of products do both, but the
|
||||
@@ -70,11 +88,12 @@ review surface is right there: the editor highlights every changed line, and acc
|
||||
click. If you already work in a graphical editor, this is the lowest-friction on-ramp.
|
||||
|
||||
**Agentic command-line tools.** These run in your terminal as a standalone program you talk to in
|
||||
plain language. You launch the tool *inside* your project directory, and it reads files, runs
|
||||
commands, and edits files on its own, reporting back what it did. They tend to be more autonomous —
|
||||
better at "go do this multi-step thing" — and they're editor-independent, so they work the same
|
||||
whether you use a graphical editor, a terminal editor, or none. The review surface is `git diff`
|
||||
itself (Module 2), which is the same review surface you'll use for everything else in this course.
|
||||
plain language (Claude Code and Aider are two). You launch the tool *inside* your project directory,
|
||||
and it reads files, runs commands, and edits files on its own, reporting back what it did. They tend
|
||||
to be more autonomous, better at "go do this multi-step thing," and they're editor-independent, so
|
||||
they work the same whether you use a graphical editor, a terminal editor, or none. The review surface
|
||||
is `git diff` itself (Module 2), the same review surface you'll use for everything else in this
|
||||
course.
|
||||
|
||||
| | Editor-integrated assistant | Agentic CLI tool |
|
||||
|---|---|---|
|
||||
@@ -109,17 +128,21 @@ brand:
|
||||
Don't agonize. Any tool that shows diffs and has an approval mode is good enough to learn the loop.
|
||||
The loop is the durable skill; the tool is swappable, same as the model.
|
||||
|
||||
**We'll use Claude Code as the worked example** from here on, so the commands below are concrete
|
||||
instead of abstract. It's an agentic CLI; wherever you see `claude`, sub your own agent. The concepts
|
||||
don't depend on it, same as the model.
|
||||
|
||||
### Wiring it up: from browser to repo
|
||||
|
||||
The exact clicks differ per tool and drift over time, so here is the shape every one of them
|
||||
follows. Do these four steps and you're connected.
|
||||
follows. Four steps connect any of them.
|
||||
|
||||
**1. Install it.** Editor-integrated assistants install from your editor's extension/plugin
|
||||
marketplace — search, install, reload. Agentic CLIs install as a command-line program (commonly via a
|
||||
package manager like `npm`/`pip`/`brew`, or a download) and then exist as a command you run, e.g.:
|
||||
|
||||
```bash
|
||||
your-agent --version # confirm the tool is on your PATH
|
||||
claude --version # sub your agent if using something else
|
||||
```
|
||||
|
||||
**2. Authenticate.** On first run the tool will send you through a sign-in — usually a browser-based
|
||||
@@ -132,7 +155,7 @@ whole point. The convention is **the current working directory is the project**:
|
||||
|
||||
```bash
|
||||
cd ~/ai-workflow-course/tasks-app # the repo from Modules 1–2
|
||||
your-agent # launch it from inside the project
|
||||
claude # launch it from inside the project
|
||||
```
|
||||
|
||||
For an editor-integrated assistant, the equivalent is **open the project folder** (`code .` or
|
||||
@@ -140,21 +163,26 @@ File → Open Folder), exactly as you did in Module 1 — the assistant scopes i
|
||||
that's open. Either way, the tool now treats this directory as its world: it can see every file in
|
||||
it without you pasting a thing.
|
||||
|
||||
**4. Confirm it can actually read the project.** Don't assume — verify, the same instinct you'd apply
|
||||
to any new integration. Ask it a question only something that has read your files could answer:
|
||||
**4. Confirm it can actually read the project.** Don't assume; verify, the same instinct you'd apply
|
||||
to any new integration. The check is to ask a question only something that has read your files could
|
||||
answer:
|
||||
|
||||
> *"What does this project do, which files is it split across, and what commands does the CLI
|
||||
> support?"*
|
||||
|
||||
A correct answer names `tasks.py` and `cli.py`, describes the task app, and lists `add` / `list` /
|
||||
`done` — pulled from the actual files, not guessed. If it asks you to paste code, or describes a
|
||||
generic to-do app it clearly invented, it is **not** connected to the repo. Stop and fix the wiring
|
||||
before going further; everything downstream assumes it can read.
|
||||
A connected tool answers from the actual files, naming `tasks.py` and `cli.py` and listing `add` /
|
||||
`list` / `done`:
|
||||
|
||||
A power move you already know from Module 2: ask it to read the *repo's* state, not just the files —
|
||||
*"run `git log`, `git status`, and `git diff` and tell me where this project is."* An agentic tool
|
||||
can run those itself. Now its first act is reading the durable memory you've been building, which is
|
||||
exactly the "where were we?" reconstruction from Module 2, except the AI does the reading.
|
||||
> *"It's a command-line to-do app. The logic lives in `tasks.py` (a `TaskList` class that persists to
|
||||
> `tasks.json`), and `cli.py` is the front end that dispatches `add`, `list`, and `done`."*
|
||||
|
||||
If instead it asks you to paste code, or describes a generic to-do app it clearly invented, it is
|
||||
**not** connected to the repo, and everything downstream assumes it can read.
|
||||
|
||||
Better still, point it at the *repo's* state, not just the files: *"run `git log`, `git status`, and
|
||||
`git diff` and tell me where this project is."* An agentic tool runs those itself, so its first act
|
||||
is reading the durable memory you built in Module 2 — the "where were we?" reconstruction, now done
|
||||
by the AI instead of pasted by you.
|
||||
|
||||
### Operating it: the edit → review → iterate loop
|
||||
|
||||
@@ -167,21 +195,19 @@ replaces the entire copy-paste loop with this:
|
||||
you what it did. No copying, no pasting, no you-as-integration-layer. This is the moment seam 1
|
||||
dies: when the change spans `tasks.py` *and* `cli.py`, the tool edits both, because it can see
|
||||
both.
|
||||
3. **Review the diff.** This is the load-bearing step, and it's the Module 2 habit, unchanged:
|
||||
|
||||
```bash
|
||||
git diff
|
||||
```
|
||||
|
||||
Read exactly what changed — every line, across every file it touched. An editor-integrated tool
|
||||
shows you the same thing in its diff view. You are reviewing the AI's work, not trusting it. (The
|
||||
deep version of this skill — spotting the plausible-but-wrong change — is Module 10. Here, just
|
||||
build the reflex: *nothing gets committed unread.*)
|
||||
4. **Iterate or revert.**
|
||||
- If it's right: run it, then commit (`git add . && git commit -m "…"`). New checkpoint.
|
||||
3. **Review the diff.** This is the load-bearing step and it stays in your hands, the Module 2 habit
|
||||
unchanged. The AI shows you what it changed: an agentic CLI runs `git diff`, an editor-integrated
|
||||
tool shows the same thing in its diff view. You read every line, across every file it touched.
|
||||
You're reviewing the AI's work, not trusting it. (The deep version of this skill, spotting the
|
||||
plausible-but-wrong change, is Module 10. Here, just build the reflex: *nothing gets committed
|
||||
unread.*)
|
||||
4. **Keep it or revert it — the AI does the git, you verify.**
|
||||
- If it's right: tell the AI to commit the reviewed change with a clear message. It stages and
|
||||
commits; you confirm the checkpoint landed (`git log`). New checkpoint.
|
||||
- If it's *close*: tell the AI what to fix and loop back to step 2. It already has the context.
|
||||
- If it's wrong: **`git restore .`** and you're back to your last checkpoint, byte for byte. The
|
||||
mess is gone. Try a different prompt.
|
||||
- If it's wrong: tell the AI to throw away its uncommitted changes. It runs the restore; you
|
||||
verify `git diff` is empty and you're back at your last checkpoint, byte for byte. The mess is
|
||||
gone. Try a different prompt.
|
||||
|
||||
That fourth step is the entire reason this is safe, so let's be explicit about it.
|
||||
|
||||
@@ -194,17 +220,17 @@ makes is a visible, reversible delta from a known-good state.**
|
||||
|
||||
Concretely, the safety contract is:
|
||||
|
||||
- **Before you let it loose:** your work is committed (`git status` is clean). That's your restore
|
||||
point.
|
||||
- **Before you let it loose:** your work is committed and `git status` is clean. (You'll have the
|
||||
agent confirm this and commit anything outstanding; you verify it.) That's your restore point.
|
||||
- **While it works:** every change is on disk, and `git diff` shows you all of it. Nothing is hidden.
|
||||
- **If it goes wrong:** `git restore .` discards every uncommitted edit it made and you're back at
|
||||
the checkpoint, with zero retyping. Module 2's "undo for the AI," now pointed at an AI that edits
|
||||
files itself.
|
||||
- **If it goes wrong:** the agent runs `git restore`, discards every uncommitted edit it made, and
|
||||
you're back at the checkpoint with zero retyping. You verify the diff is empty. Module 2's "undo
|
||||
for the AI," now an undo the AI even performs for you.
|
||||
|
||||
This is the promise Module 2 made cashing out. Module 2 said *every later module asks you to let the
|
||||
AI do something bolder, and you can say yes because you can always get back to a checkpoint.* This is
|
||||
the first of those bolder things. The downside of any AI edit is now "throw away a few minutes and
|
||||
re-prompt" — never "lose work" — and that asymmetry is what lets you move fast.
|
||||
re-prompt," never "lose work," and that asymmetry is what lets you move fast.
|
||||
|
||||
> **The one rule:** start from a clean commit. If `git status` shows uncommitted work before you turn
|
||||
> the AI loose, you've blurred the line between *your* work and *its* work — and `git restore .` will
|
||||
@@ -227,7 +253,7 @@ an approval model, usually some version of:
|
||||
|
||||
The right setting is a function of your safety net, not your nerve. With a clean commit you can
|
||||
afford a looser setting for edits, because the diff is reversible. Be more conservative about letting
|
||||
it *run* commands unattended — a deleted file is restorable; a command that hits a real external
|
||||
it *run* commands unattended: a deleted file is restorable; a command that hits a real external
|
||||
system may not be. Match the leash to what you can undo.
|
||||
|
||||
---
|
||||
@@ -248,8 +274,8 @@ pays off. Map it straight back to Module 1's three seams:
|
||||
|
||||
The deeper point: notice that *none of this is model-specific.* You didn't get a smarter model. You
|
||||
gave the same model **access** and wrapped it in **review and revert**. That's the course thesis in
|
||||
miniature — the leverage came from the workflow around the model, not the model. Swap the model
|
||||
underneath this loop and the loop is unchanged.
|
||||
miniature: the workflow around the model did the work, not the model. Swap the model underneath this
|
||||
loop and the loop is unchanged.
|
||||
|
||||
---
|
||||
|
||||
@@ -265,42 +291,44 @@ copy-paste loop back in Module 1, now done right.
|
||||
**You'll need:**
|
||||
|
||||
- The `tasks-app` repo from Modules 1–2, as a Git repo with at least one commit.
|
||||
- One AI-out-of-the-browser tool of your choice — either an editor-integrated assistant or an agentic
|
||||
CLI. Use the "How to choose" criteria above; any tool that shows diffs and has an approval mode is
|
||||
fine.
|
||||
- One AI-out-of-the-browser tool. We'll use **Claude Code** as the example; sub your own agent (an
|
||||
editor-integrated assistant or another agentic CLI). Use the "How to choose" criteria above; any
|
||||
tool that shows diffs and has an approval mode is fine.
|
||||
- Your model/provider credentials for that tool.
|
||||
- The verify script in this module's `lab/verify.sh`. **Convention for every lab script from here on:**
|
||||
the course's scripts live in the course repo under `modules/NN/lab/`, but your `tasks-app` is a
|
||||
separate folder (Module 1) — so when a step runs one, **copy the script into `tasks-app` first, then
|
||||
run it by name**. (Same copy-it-in move you used for the instructions file in Module 5; use the real
|
||||
path to wherever you unzipped the course in place of `/path/to/`.)
|
||||
the course's scripts live under `~/ai-workflow-course/modules/NN/lab/`, but your `tasks-app` is a
|
||||
separate folder (Module 1), so when a step runs one, **copy the script into `tasks-app` first, then
|
||||
run it by name**. (Paths below assume the course unzipped to `~/ai-workflow-course/`; adjust if you
|
||||
put it elsewhere.)
|
||||
|
||||
### Part A — Wire it up and confirm it can read
|
||||
|
||||
1. Install the tool and authenticate it (steps 1–2 in "Wiring it up").
|
||||
|
||||
2. Point it at the repo (step 3): `cd ~/ai-workflow-course/tasks-app` and launch the agentic CLI from
|
||||
there, **or** open that folder in your editor and open the assistant's agent panel.
|
||||
2. Point it at the repo (step 3): `cd ~/ai-workflow-course/tasks-app` and launch `claude` from there,
|
||||
**or** open that folder in your editor and open the assistant's agent panel.
|
||||
|
||||
3. **Confirm read access** (step 4). Ask:
|
||||
|
||||
> *"What does this project do, which files is it split across, and what commands does the CLI
|
||||
> support?"*
|
||||
|
||||
You're connected only if it names `tasks.py` and `cli.py` and lists `add` / `list` / `done` from
|
||||
the real files. If it asks you to paste code, fix the wiring before continuing.
|
||||
3. **Confirm read access** (step 4). Ask it the read-check question from "Wiring it up." You're
|
||||
connected only if it answers from the real files; if it asks you to paste code, fix the wiring
|
||||
before continuing.
|
||||
|
||||
### Part B — Start from a clean checkpoint
|
||||
|
||||
4. This is the one rule. Make sure your work is committed so the AI's change is the *only* thing in
|
||||
the next diff:
|
||||
4. This is the one rule: start clean, so the AI's change is the *only* thing in the next diff. **Tell
|
||||
the agent to set the checkpoint**, then verify it yourself. Ask:
|
||||
|
||||
> *"Check `git status`. If anything's uncommitted, commit it with a clear message so we start from
|
||||
> a clean tree."*
|
||||
|
||||
Then confirm with your own eyes:
|
||||
|
||||
```bash
|
||||
git status # must be clean ("nothing to commit, working tree clean")
|
||||
git status # you check: "nothing to commit, working tree clean"
|
||||
```
|
||||
|
||||
If it isn't clean, commit your current work first (`git add . && git commit -m "…"`). Now you have
|
||||
a known-good restore point, and anything that appears in `git diff` next is purely the AI's.
|
||||
Now you have a known-good restore point, and anything that appears in `git diff` next is purely
|
||||
the AI's. (Notice you directed the commit and verified the result — you didn't type it. That's the
|
||||
split for every git step from here on.)
|
||||
|
||||
### Part C — Make a real multi-file change
|
||||
|
||||
@@ -329,43 +357,49 @@ copy-paste loop back in Module 1, now done right.
|
||||
both files. Copy it into `tasks-app` first (see *You'll need*), then run it from there:
|
||||
|
||||
```bash
|
||||
cp /path/to/modules/04-getting-the-ai-out-of-the-browser/lab/verify.sh .
|
||||
cp ~/ai-workflow-course/modules/04-getting-the-ai-out-of-the-browser/lab/verify.sh .
|
||||
bash verify.sh
|
||||
```
|
||||
|
||||
It should add tasks, delete one by index, and confirm the right task remains. If it fails, don't
|
||||
hand-fix it — tell the AI what broke and let it iterate (step 4 of the loop), then re-run.
|
||||
hand-fix it; tell the AI what broke and let it iterate (step 4 of the loop), then re-run.
|
||||
|
||||
8. **Commit the reviewed change — this is your new checkpoint.** It passed your own eyes and it
|
||||
passes the check, so lock it in:
|
||||
8. **Commit the reviewed change — tell the agent, then verify.** It passed your own eyes and it
|
||||
passes the check, so lock it in. Ask the agent:
|
||||
|
||||
> *"Commit this with the message 'Add delete command (made via editor/CLI agent)'."*
|
||||
|
||||
It stages and commits. You verify the checkpoint landed:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Add delete command (made via editor/CLI agent)"
|
||||
git log --oneline
|
||||
git log --oneline # your new commit is on top
|
||||
```
|
||||
|
||||
You just shipped a reviewed, multi-file change made by an AI editing your files directly — and the
|
||||
copy-paste loop never entered into it. This commit is now the clean state `git restore .` falls
|
||||
back to in the next part.
|
||||
You just shipped a reviewed, multi-file change an AI made by editing your files directly, and you
|
||||
never typed the commit. This commit is now the clean state the AI's `git restore` falls back to in
|
||||
the next part.
|
||||
|
||||
### Part D — Practice the revert (do this even though it works)
|
||||
|
||||
9. You only trust an undo you've used. Your tree is clean — you just committed in Part C, which is
|
||||
exactly the safe setup the one rule demands. Prove the net is under you: ask the tool for a
|
||||
deliberately throwaway change —
|
||||
9. You only trust an undo you've used. Your tree is clean (you just committed in Part C, exactly the
|
||||
safe setup the one rule demands). Prove the net is under you. Ask the tool for a deliberately
|
||||
throwaway change:
|
||||
|
||||
> *"Rename every variable in `tasks.py` to single letters."*
|
||||
|
||||
— let it apply it, glance at `git diff` to see the damage, then throw it away:
|
||||
Let it apply it, glance at `git diff` to see the damage, then **tell the agent to undo it**:
|
||||
|
||||
> *"Throw away everything you just did and get us back to the last commit."*
|
||||
|
||||
It runs the restore. Now you verify the rescue:
|
||||
|
||||
```bash
|
||||
git restore .
|
||||
git diff # empty — the AI's mess is gone, byte for byte
|
||||
bash verify.sh # still passes — you're back at your good state (you copied it in at step 7)
|
||||
```
|
||||
|
||||
That's the Module 2 safety net catching a Module 4 mistake. Internalize how cheap that was.
|
||||
That's the Module 2 safety net catching a Module 4 mistake, and the AI even performed the undo on
|
||||
your word. Internalize how cheap that was.
|
||||
|
||||
### Part E — Confirm you're back at your good state
|
||||
|
||||
@@ -387,13 +421,13 @@ copy-paste loop back in Module 1, now done right.
|
||||
Be honest about the limits of working this way:
|
||||
|
||||
- **Access is not judgment.** The AI reading your whole repo makes it *informed*, not *correct*. It
|
||||
will still make confident, plausible, wrong changes — now across multiple files at once, which is a
|
||||
will still make confident, plausible, wrong changes, now across multiple files at once, which is a
|
||||
bigger mess to read. The diff review in step 3 of the loop is not optional, and the deep version of
|
||||
that skill is a whole module of its own (Module 10). The tool removed the copy-paste; it did not
|
||||
remove the reviewing.
|
||||
- **`git restore .` only saves you if you committed first.** This is the one rule for a reason. If
|
||||
you let the AI loose on a dirty tree, restore can't tell your work from its work and throws away
|
||||
both. The discipline that makes this module safe is *commit before you turn it loose* — the same
|
||||
both. The discipline that makes this module safe is *commit before you turn it loose*, the same
|
||||
"commit often" lesson from Module 2, now with teeth.
|
||||
- **It can do more than edit — watch what it runs.** An agentic tool that can run commands can do
|
||||
things `git restore` cannot undo: delete files outside the repo, hit a network service, mutate a
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# care HOW the AI implemented it, only that `delete` works end to end.
|
||||
#
|
||||
# Copy this into your tasks-app project directory, then run it from there:
|
||||
# cp /path/to/modules/04-getting-the-ai-out-of-the-browser/lab/verify.sh .
|
||||
# cp ~/ai-workflow-course/modules/04-getting-the-ai-out-of-the-browser/lab/verify.sh .
|
||||
# bash verify.sh
|
||||
#
|
||||
# (It self-locates cli.py, so it also still works if you run it in place as `bash lab/verify.sh`.)
|
||||
|
||||
Reference in New Issue
Block a user