fix(M7-27+capstone): apply AI-drives-git reframe, lesson=theory, de-slop course-wide
Phase 2 sweep — all modules are post-pivot, so the learner directs the AI agent
(Claude Code as the worked example) to do the git/setup work and verifies, instead
of typing commands by hand; no re-teaching basics. Lesson sections are theory with
example output; all execution lives in the labs. De-slopped ("prose" etc. gone
course-wide, em-dash density thinned). /path/to placeholders -> ~/ai-workflow-course.
Every deliberate teaching device verified intact: M10 ai-change.patch trap,
M12 bad-clear-snippet, M13/M27 planted pending_count bug, M15 secret+typosquat+MD5,
M18 BREAK=1, M21 absent-.gitignore, M22 poisoned skill, M24 no-op patch, M25 --simulate.
Labs compile/parse (py/sh/yaml/json); no junk.
Closes #83
Closes #86
Closes #89
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:
@@ -1,26 +1,26 @@
|
||||
# Module 21 — Skills: Teaching the AI Your Playbook
|
||||
|
||||
> **Stop re-explaining your own procedures.** A skill is a repeatable workflow written down once,
|
||||
> committed, and invoked on demand — so the AI does the thing *your* way, the same way, every time,
|
||||
> committed, and invoked on demand, so the AI does the thing *your* way, the same way, every time,
|
||||
> without you narrating the steps again.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Module 2** — you commit, read diffs, and treat the repo as durable memory. Skills live in that
|
||||
- **Module 2:** you commit, read diffs, and treat the repo as durable memory. Skills live in that
|
||||
repo and are versioned exactly like code.
|
||||
- **Module 3** — markdown-as-versioned-text, and the `CHANGELOG.md` convention this module's lab
|
||||
- **Module 3:** markdown-as-versioned-text, and the `CHANGELOG.md` convention this module's lab
|
||||
writes to.
|
||||
- **Module 4** — the AI lives in your editor/CLI and reads your files directly. A skill is a file it
|
||||
- **Module 4:** the AI lives in your editor/CLI and reads your files directly. A skill is a file it
|
||||
loads; a browser chat can't pick one up automatically.
|
||||
- **Module 5 — the one this builds on directly.** You committed an always-on instructions file that
|
||||
tells the AI how the project works in general. This module is its **structured big sibling**: the
|
||||
same write-it-down-and-commit instinct, but for *specific repeatable procedures* invoked on demand.
|
||||
- **Module 13** — what a real test is (and why "it didn't crash" isn't one). The lab's procedure
|
||||
- **Module 13:** what a real test is (and why "it didn't crash" isn't one). The lab's procedure
|
||||
includes writing one.
|
||||
- *Helpful, not required:* **Module 20 (MCP)** — a skill's steps can call the real tools an MCP
|
||||
server exposes, which is where playbooks get genuinely powerful.
|
||||
- *Helpful, not required:* **Module 20 (MCP).** A skill's steps can call the real tools an MCP
|
||||
server exposes, which is where a playbook reaches beyond editing files into live systems.
|
||||
|
||||
---
|
||||
|
||||
@@ -28,14 +28,14 @@
|
||||
|
||||
By the end of this module you can:
|
||||
|
||||
1. Explain the difference between an **always-on instructions file (Module 5)** and a **skill** — and
|
||||
1. Explain the difference between an **always-on instructions file (Module 5)** and a **skill**, and
|
||||
say when each is the right tool.
|
||||
2. Write a skill: a structured, named, invokable playbook for a recurring task, in your tool's
|
||||
format-agnostic essentials (when-to-use, inputs, ordered steps, done-criteria).
|
||||
3. Have the AI **execute** a skill end to end and verify it followed every step.
|
||||
4. Keep skills in version control so a procedure is shareable, reviewable, and recoverable like any
|
||||
other artifact.
|
||||
5. Recognize when a one-off prompt has earned promotion into a durable skill — and when it hasn't.
|
||||
5. Recognize when a one-off prompt has earned promotion into a durable skill, and when it hasn't.
|
||||
|
||||
---
|
||||
|
||||
@@ -43,14 +43,14 @@ By the end of this module you can:
|
||||
|
||||
### The pain: you keep narrating the same procedure
|
||||
|
||||
You've written the Module 5 instructions file, and it's working — the AI knows your layout, your test
|
||||
You've written the Module 5 instructions file, and it's working. The AI knows your layout, your test
|
||||
command, your off-limits files. But there's a class of knowledge it doesn't cover: **multi-step
|
||||
procedures you run again and again.**
|
||||
|
||||
"Add a new CLI command" is the canonical example. Done properly it's never one edit — it's: put the
|
||||
"Add a new CLI command" is the canonical example. Done properly it's never one edit. It's: put the
|
||||
logic in the right file, wire the CLI, write a test that actually checks the behavior, run the tests,
|
||||
smoke-test the command, add a changelog line, commit it as one clean change. The AI can do every step.
|
||||
But left to a bare prompt — *"add a `clear` command"* — it'll usually give you the code and forget the
|
||||
But left to a bare prompt (*"add a `clear` command"*) it'll usually give you the code and forget the
|
||||
test, or skip the changelog, or commit `tasks.json` along for the ride. So you spell out the seven
|
||||
steps. It works. Next week you add another command and **you spell out the same seven steps again.**
|
||||
|
||||
@@ -65,10 +65,10 @@ stored as a file in the repo and loaded **on demand** when that procedure is the
|
||||
|
||||
Strip the vendor branding and every skill has the same four parts:
|
||||
|
||||
- **A name and a "when to use it."** So both you and the AI know which playbook applies — and, just as
|
||||
- **A name and a "when to use it."** So both you and the AI know which playbook applies and, just as
|
||||
importantly, when it *doesn't*.
|
||||
- **Inputs.** The few things the procedure needs to be told (here: the command name and what it does).
|
||||
- **Ordered steps.** The actual procedure — the commands, the files, the checks, in sequence, with the
|
||||
- **Ordered steps.** The actual procedure: the commands, the files, the checks, in sequence, with the
|
||||
non-negotiables marked ("run the tests before claiming success," "don't stage `tasks.json`").
|
||||
- **Done-criteria.** How the AI (and you) know it's actually finished, not just "produced something."
|
||||
|
||||
@@ -93,12 +93,12 @@ file; graduate a procedure into a skill when it earns its own page.
|
||||
|
||||
### Why "on demand" is the whole point
|
||||
|
||||
Module 5 warned that **bloat kills an instructions file** — a 300-line always-on briefing gets read
|
||||
Module 5 warned that **bloat kills an instructions file**: a 300-line always-on briefing gets read
|
||||
the way you read a terms-of-service. So you *can't* solve the re-narration problem by stuffing every
|
||||
procedure into the always-on file; you'd drown the signal that makes it work.
|
||||
|
||||
Skills are the escape hatch. Because a skill loads only when its procedure is the task, you can write
|
||||
it in full detail — every step, every guardrail — without taxing every unrelated session. Ten skills
|
||||
A skill solves that. Because a skill loads only when its procedure is the task, you can write
|
||||
it in full detail, every step and every guardrail, without taxing every unrelated session. Ten skills
|
||||
cost the AI nothing on a session that invokes none of them. This is **progressive disclosure**: keep
|
||||
the always-on context lean, and pull in the deep procedure exactly when it's needed. It's the same
|
||||
reason you don't tape every recipe you own to the kitchen wall.
|
||||
@@ -111,12 +111,12 @@ text applies to it directly:
|
||||
|
||||
- **Recoverable and historied (Module 2).** A skill has a `git log`. You can see when a step was added
|
||||
and why, and `git restore` a botched edit. The procedure is a checkpoint like any other.
|
||||
- **Shareable (Modules 8 & 11).** Push the repo and the whole team — and every agent that later
|
||||
operates on it — inherits the same playbook. Nobody runs their own private version of "how we add a
|
||||
- **Shareable (Modules 8 & 11).** Push the repo and the whole team, plus every agent that later
|
||||
operates on it, inherits the same playbook. Nobody runs their own private version of "how we add a
|
||||
command." It's the Module 5 anti-drift argument, applied to procedures.
|
||||
- **Reviewable (Module 10).** Changing how the AI performs a procedure arrives as a **diff in a PR**.
|
||||
Tightening "add a test" into "add a test that asserts the end state, not just no-crash" is a
|
||||
reviewable change to your team's workflow — not an invisible tweak in one person's setup.
|
||||
reviewable change to your team's workflow, not an invisible tweak in one person's setup.
|
||||
|
||||
A prompt you keep in your head dies with the session. A skill in the repo is durable, shared
|
||||
capability. That's the upgrade: from one-off prompting to a versioned, reviewable asset.
|
||||
@@ -124,7 +124,7 @@ capability. That's the upgrade: from one-off prompting to a versioned, reviewabl
|
||||
### Naming the pattern, not the vendor
|
||||
|
||||
"Skills" is one name for this. Tools also call them custom commands, slash commands, recipes, prompts,
|
||||
playbooks, or modes, and they load them differently — some auto-discover a dedicated folder, some need
|
||||
playbooks, or modes, and they load them differently: some auto-discover a dedicated folder, some need
|
||||
you to point at a file, some let your always-on instructions file say *"when asked to add a command,
|
||||
follow `add-command.md`."* **The durable pattern is the same in all of them: a named, invokable file
|
||||
of structured steps for a repeatable procedure, kept in the repo.** Learn the pattern; map it onto
|
||||
@@ -133,24 +133,24 @@ the playbook you wrote is the part that lasts.
|
||||
|
||||
### Skills compose with your tools
|
||||
|
||||
A skill's steps aren't limited to editing files. They can drive the test runner, the CLI, Git — and,
|
||||
A skill's steps aren't limited to editing files. They can drive the test runner, the CLI, Git, and,
|
||||
once you have **Module 20's MCP** servers wired up, the real systems behind them (open the issue, hit
|
||||
the staging API, query the database). A skill is where you encode *"use these hands, in this order, to
|
||||
get this outcome."* The deeper your toolchain, the more a written playbook is worth — because there
|
||||
get this outcome."* The deeper your toolchain, the more a written playbook is worth, because there
|
||||
are more steps to get wrong, and more value in getting them right every time.
|
||||
|
||||
---
|
||||
|
||||
## The AI angle
|
||||
|
||||
On paper this is just "write a runbook." The AI-specific twist is what makes it land:
|
||||
On paper this is just "write a runbook." The AI-specific twist is what changes the stakes:
|
||||
|
||||
- **The AI will execute the playbook, not just read it.** A runbook for a human is a reminder; a skill
|
||||
for an agent is something it *performs*. The precision pays off immediately — vague step, vague
|
||||
for an agent is something it *performs*. The precision pays off immediately: vague step, vague
|
||||
result; imperative step ("run `python -m unittest`; do not claim success until it's green"), reliable
|
||||
result.
|
||||
- **The AI is confidently incomplete without one.** Asked to "add a command," it'll happily stop at
|
||||
the code and skip the test, the changelog, the clean commit — and sound finished doing it. The skill
|
||||
the code and skip the test, the changelog, the clean commit, and sound finished doing it. The skill
|
||||
is how you make *complete* the default instead of a thing you have to keep catching.
|
||||
- **The skill outlives the model.** Swap models next quarter and the playbook carries over unchanged.
|
||||
You encoded the *procedure*, not the prompt that happened to coax it out of this month's model. The
|
||||
@@ -163,43 +163,46 @@ On paper this is just "write a runbook." The AI-specific twist is what makes it
|
||||
**Lab language:** markdown (the skill file) plus shell and Python (the `tasks-app`). You'll write a
|
||||
skill, then have your editor-integrated AI (Module 4) execute it.
|
||||
|
||||
You'll write a skill for the procedure from *Key concepts* — **add a new `tasks-app` command, end to
|
||||
end: code + test + changelog + clean commit** — and then watch the AI run it on a command it's never
|
||||
You'll write a skill for the procedure from *Key concepts*, **add a new `tasks-app` command, end to
|
||||
end: code + test + changelog + clean commit**, and then watch the AI run it on a command it's never
|
||||
seen, producing all four parts without you listing the steps.
|
||||
|
||||
**You'll need:**
|
||||
|
||||
- Your agentic coding tool from Module 4, and knowledge of how it loads a procedure (a skills/commands
|
||||
folder it auto-discovers, or simply pointing it at a file by name — check its docs).
|
||||
folder it auto-discovers, or simply pointing it at a file by name; check its docs).
|
||||
- A Python 3.10+ `tasks-app`. Use the snapshot in this module's `lab/tasks-app/` (it has `add`,
|
||||
`list`, `done`, `count`, a `test_tasks.py`, and a `CHANGELOG.md`), or carry forward your own from
|
||||
earlier modules. Make it a Git repo if it isn't: `git init && git add . && git commit -m "Start"`.
|
||||
earlier modules. It should already be a Git repo from earlier modules; if you're starting fresh,
|
||||
ask Claude Code (`claude` in the project; sub your own agent) to initialize it and commit a
|
||||
baseline, then confirm with `git log` that the first commit landed.
|
||||
|
||||
### Part A — Install the skill
|
||||
|
||||
1. Copy this module's starter skill, `lab/add-command-skill.md`, into your `tasks-app` repo wherever
|
||||
your tool expects procedures. If your tool auto-discovers a folder, put it there under a clear name
|
||||
(e.g. `add-command.md`). If it doesn't, just drop it at the repo root — you'll invoke it by name.
|
||||
(e.g. `add-command.md`). If it doesn't, just drop it at the repo root and invoke it by name.
|
||||
|
||||
```bash
|
||||
cd ~/ai-workflow-course/tasks-app
|
||||
cp /path/to/modules/21-skills-teaching-the-ai-your-playbook/lab/add-command-skill.md add-command.md
|
||||
cp ~/ai-workflow-course/modules/21-skills-teaching-the-ai-your-playbook/lab/add-command-skill.md add-command.md
|
||||
```
|
||||
|
||||
2. Read it. The whole file is short on purpose — when-to-use, inputs, seven ordered steps, and
|
||||
2. Read it. The whole file is short on purpose: when-to-use, inputs, seven ordered steps, and
|
||||
done-criteria. Confirm every project fact in it matches *your* app (test command, file names, the
|
||||
off-limits `tasks.json`). A skill with wrong facts misdirects the AI worse than no skill.
|
||||
|
||||
3. **Commit it.** This is the point — the procedure now lives in version control:
|
||||
3. **Commit it.** This is the point: the procedure now lives in version control. Ask Claude Code
|
||||
(sub your own agent) to commit the new skill file with a message like "Add skill: add a tasks-app
|
||||
command end to end," then verify it landed:
|
||||
|
||||
```bash
|
||||
git add add-command.md
|
||||
git commit -m "Add skill: add a tasks-app command end to end"
|
||||
git log --oneline -1 # the skill commit, by name
|
||||
```
|
||||
|
||||
### Part B — Invoke it
|
||||
|
||||
4. Start a **fresh** AI session in your editor and invoke the skill the way your tool does it — its
|
||||
4. Start a **fresh** AI session in your editor and invoke the skill the way your tool does it: its
|
||||
slash command / skill name, or plainly: *"Follow `add-command.md` to add a `clear` command that
|
||||
removes all tasks."* Crucially, **don't list the steps yourself.** The skill is supposed to supply
|
||||
them.
|
||||
@@ -223,9 +226,9 @@ seen, producing all four parts without you listing the steps.
|
||||
```
|
||||
|
||||
If a step was skipped, that's the lab working: it shows you exactly where your wording was too soft.
|
||||
Tighten that line, commit the skill change, and run it again on a second command (`high <index>` to
|
||||
flag a task, say). **A skill you improve once and reuse forever is the deliverable** — not the one
|
||||
`clear` command.
|
||||
Tighten that line, have Claude Code (sub your own agent) commit the skill edit while you verify the
|
||||
diff, and run it again on a second command (`high <index>` to flag a task, say). **A skill you
|
||||
improve once and reuse forever is the deliverable**, not the one `clear` command.
|
||||
|
||||
### Part D — See it as a reviewable, reusable asset
|
||||
|
||||
@@ -239,7 +242,7 @@ seen, producing all four parts without you listing the steps.
|
||||
(`git log -p` surfaces the skill's own patches no matter what you committed *after* tightening it —
|
||||
unlike `git diff HEAD~1`, which would be empty here because the most recent commit added the second
|
||||
*command*, not a change to the skill.) Each entry in that history *is* a change to how your team adds
|
||||
commands — readable, attributable, revertable. In a
|
||||
commands: readable, attributable, revertable. In a
|
||||
team repo (Modules 8, 11) it reaches everyone on `git pull`; behind review (Module 10) it lands as a
|
||||
PR someone approves. You've turned a procedure you used to narrate into a versioned capability.
|
||||
|
||||
@@ -249,7 +252,7 @@ seen, producing all four parts without you listing the steps.
|
||||
|
||||
- **A skill is guidance, not enforcement — same caveat as Module 5.** It strongly biases the AI; it
|
||||
doesn't bind it. The agent can still skip a step, especially a soft one, especially late in a long
|
||||
session. The steps that *can't* be skipped are the ones backed by **CI (Module 14)** — the test the
|
||||
session. The steps that *can't* be skipped are the ones backed by **CI (Module 14)**: the test the
|
||||
skill tells it to write only truly gates anything once a pipeline runs it on every push. Write the
|
||||
done-criteria as hard checks, and let CI be the backstop.
|
||||
- **Skills rot.** A playbook that says "tests run with X" after you've moved to Y will confidently
|
||||
@@ -257,13 +260,13 @@ seen, producing all four parts without you listing the steps.
|
||||
longer run. Committing them (so changes are visible) is what makes that maintainable.
|
||||
- **Don't skillify everything.** A skill earns its place when a procedure is *repeated*, *multi-step*,
|
||||
and *gets done wrong without one*. A one-off task doesn't need a playbook, and a pile of near-duplicate
|
||||
skills is its own kind of bloat — now you're maintaining ten files and the AI has to pick the right
|
||||
skills is its own kind of bloat: now you're maintaining ten files and the AI has to pick the right
|
||||
one. Promote a prompt to a skill the third time you've typed it, not the first.
|
||||
- **Overlap with the always-on file causes drift.** If a fact lives in both your Module 5 instructions
|
||||
file *and* a skill, you'll eventually update one and not the other. Keep general facts in the
|
||||
always-on file and *reference* them from skills; don't duplicate them.
|
||||
- **A skill is not a security boundary.** "Don't stage `tasks.json`" is a convention, not a permission.
|
||||
An installed third-party skill is untrusted code that runs against your repo — vetting, permissions,
|
||||
An installed third-party skill is untrusted code that runs against your repo; vetting, permissions,
|
||||
and prompt-injection defense are **Module 22's** job, immediately next, for exactly this reason.
|
||||
|
||||
---
|
||||
@@ -274,8 +277,8 @@ seen, producing all four parts without you listing the steps.
|
||||
|
||||
- Your `tasks-app` repo has a committed skill file for "add a command," with `git log` showing the
|
||||
commit that added it.
|
||||
- You've invoked that skill and watched a fresh AI session produce **all four** parts — code, a real
|
||||
test, a changelog entry, and one clean commit — *without you listing the steps that session*.
|
||||
- You've invoked that skill and watched a fresh AI session produce **all four** parts (code, a real
|
||||
test, a changelog entry, and one clean commit) *without you listing the steps that session*.
|
||||
- You've verified it against the skill's done-criteria (tests green, command works, the commit
|
||||
contains the right files and not `tasks.json`) rather than trusting the AI's summary.
|
||||
- You can state, in one sentence, when to put knowledge in the always-on instructions file (Module 5)
|
||||
@@ -283,8 +286,8 @@ seen, producing all four parts without you listing the steps.
|
||||
in a playbook invoked on demand.
|
||||
|
||||
When adding the *next* command is "invoke the skill" instead of "re-explain the seven steps," the
|
||||
playbook is doing its job. Module 22 comes next, and not by accident: Unit 4 just gave the AI hands —
|
||||
MCP servers and skills — and the very next thing is securing them, because an installed skill or
|
||||
playbook is doing its job. Module 22 comes next, and not by accident: Unit 4 just gave the AI hands,
|
||||
MCP servers and skills, and the very next thing is securing them, because an installed skill or
|
||||
server is untrusted code running in your environment.
|
||||
|
||||
---
|
||||
@@ -296,7 +299,7 @@ time:
|
||||
|
||||
- [ ] **Skill terminology and mechanics.** Confirm how mainstream agentic tools name and load skills
|
||||
(skills / custom commands / slash commands / recipes / prompts), whether they auto-discover a
|
||||
folder or need an explicit pointer, and any required file format/frontmatter — without pinning
|
||||
folder or need an explicit pointer, and any required file format/frontmatter, without pinning
|
||||
the lesson to one vendor. Update the "Naming the pattern" paragraph if the common vocabulary has
|
||||
shifted.
|
||||
- [ ] **No vendor leaked in.** Verify the module still names the *pattern*, not one implementation, and
|
||||
|
||||
Reference in New Issue
Block a user