Use python3 as the canonical command name course-wide (#104) (#105)
CI / check (push) Successful in 7s
Sync course wiki / sync-wiki (push) Successful in 4s

This commit was merged in pull request #105.
This commit is contained in:
2026-06-23 20:25:05 -04:00
parent 7f439212ac
commit 95e5911957
102 changed files with 380 additions and 378 deletions
@@ -87,7 +87,7 @@ This is the distinction to lock in, because the two are siblings and easy to con
| Analogy | The standing house rules posted on the wall | A labeled recipe card you pull out when you cook that dish |
They're complementary. The instructions file is the right home for facts true *all the time* ("tests
run with `python -m unittest`"). A skill is the right home for a procedure you run *sometimes* ("here
run with `python3 -m unittest`"). A skill is the right home for a procedure you run *sometimes* ("here
is exactly how we add a command"). Module 5 even told you this was coming: start with the always-on
file; graduate a procedure into a skill when it earns its own page.
@@ -147,7 +147,7 @@ On paper this is just "write a runbook." The AI-specific twist is what changes t
- **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
result; imperative step ("run `python -m unittest`; do not claim success until it's green"), reliable
result; imperative step ("run `python3 -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
@@ -222,8 +222,8 @@ seen, producing all four parts without you listing the steps.
5. Watch it perform the procedure. A correctly-followed skill will, without you saying any of it:
- add `clear()` to `tasks.py` and wire a `clear` branch into `cli.py` (logic in the right file);
- add a real test to `test_tasks.py` that asserts the list is empty afterward (not just "no crash");
- run `python -m unittest` and show it green;
- smoke-test `python cli.py clear` and show the output;
- run `python3 -m unittest` and show it green;
- smoke-test `python3 cli.py clear` and show the output;
- add a `CHANGELOG.md` line;
- stage code + test + changelog into one commit, **without** `tasks.json`.
@@ -232,8 +232,8 @@ seen, producing all four parts without you listing the steps.
6. Don't take the AI's word for it. Check against the skill's own done-criteria:
```bash
python -m unittest # green, and a clear-related test is present
python cli.py add "x" && python cli.py clear && python cli.py list # -> (no tasks yet)
python3 -m unittest # green, and a clear-related test is present
python3 cli.py add "x" && python3 cli.py clear && python3 cli.py list # -> (no tasks yet)
git show --stat HEAD # one commit: tasks.py, cli.py, test_tasks.py, CHANGELOG.md; no tasks.json
```
@@ -318,6 +318,6 @@ time:
that the example skill format stays generic (when-to-use / inputs / steps / done-criteria).
- [ ] **Dependency chain intact.** Confirm Module 20 (MCP) and Module 22 (securing servers/skills) are
still numbered as referenced, and that nothing here leans on a tool introduced after Module 20.
- [ ] **Lab still runs.** `python -m unittest` is green in `lab/tasks-app/`, and the `clear`-command
- [ ] **Lab still runs.** `python3 -m unittest` is green in `lab/tasks-app/`, and the `clear`-command
walkthrough still matches the starter files (`add`/`list`/`done`/`count`, `test_tasks.py`,
`CHANGELOG.md`).
@@ -24,7 +24,7 @@ Ask for these if they weren't given:
- Core logic lives in `tasks.py` (the `TaskList` class). The CLI front end is `cli.py`. State
persists to `tasks.json`. **Never edit `tasks.json` by hand; it's generated.**
- Tests live in `test_tasks.py` and run with `python -m unittest`. Standard library only; no
- Tests live in `test_tasks.py` and run with `python3 -m unittest`. Standard library only; no
third-party packages, no new dependencies.
- The human-facing change log is `CHANGELOG.md`, newest entry on top.
@@ -42,10 +42,10 @@ Ask for these if they weren't given:
crash." Assert the end state (e.g. after `clear()`, `len(tasks) == 0` and `pending()` is empty).
A test that passes against a broken implementation is worse than no test.
4. **Run the tests.** `python -m unittest` from the project root. Do not claim success until it's
4. **Run the tests.** `python3 -m unittest` from the project root. Do not claim success until it's
green. If it fails, fix the code, not the test, and run again.
5. **Smoke-test the CLI.** Actually run it: `python cli.py COMMAND_NAME`, then `python cli.py list`
5. **Smoke-test the CLI.** Actually run it: `python3 cli.py COMMAND_NAME`, then `python3 cli.py list`
to confirm the visible result. Paste what you ran and what it printed.
6. **Add a `CHANGELOG.md` entry.** One line under the top heading, present tense:
@@ -57,8 +57,8 @@ Ask for these if they weren't given:
## Done when
- `python -m unittest` is green and includes a new test that actually exercises `COMMAND_NAME`.
- `python cli.py COMMAND_NAME` does `WHAT_IT_DOES` and you've shown the output.
- `python3 -m unittest` is green and includes a new test that actually exercises `COMMAND_NAME`.
- `python3 cli.py COMMAND_NAME` does `WHAT_IT_DOES` and you've shown the output.
- `CHANGELOG.md` has a new top line for the command.
- One commit contains the code, the test, and the changelog line, and nothing else (no
`tasks.json`, no unrelated reformatting).
@@ -1,9 +1,9 @@
"""Tiny command-line front end for the demo task app.
Run it:
python cli.py add "write the lesson"
python cli.py list
python cli.py count
python3 cli.py add "write the lesson"
python3 cli.py list
python3 cli.py count
State is kept in tasks.json next to this file. The same minimal app from Module 1 onward; the
target your "add a command" skill extends.
@@ -32,7 +32,7 @@ def save(tlist: TaskList) -> None:
def main(argv: list[str]) -> int:
tlist = load()
if not argv:
print("usage: python cli.py [add <title> | list | done <index> | count]")
print("usage: python3 cli.py [add <title> | list | done <index> | count]")
return 1
command = argv[0]
@@ -1,6 +1,6 @@
"""Test suite for the tasks-app. Run from this folder with:
python -m unittest
python3 -m unittest
Your "add a command" skill should ADD a test here for every new command. The point is to assert
intended behavior, not just that nothing crashed.
@@ -1,9 +1,9 @@
"""Tiny command-line front end for the demo task app.
Run it:
python cli.py add "write the lesson"
python cli.py list
python cli.py count
python3 cli.py add "write the lesson"
python3 cli.py list
python3 cli.py count
State is kept in tasks.json next to this file. The same minimal app from Module 1 onward; the
target your "add a command" skill extends.
@@ -32,7 +32,7 @@ def save(tlist: TaskList) -> None:
def main(argv: list[str]) -> int:
tlist = load()
if not argv:
print("usage: python cli.py [add <title> | list | done <index> | count]")
print("usage: python3 cli.py [add <title> | list | done <index> | count]")
return 1
command = argv[0]
@@ -1,6 +1,6 @@
"""Test suite for the tasks-app. Run from this folder with:
python -m unittest
python3 -m unittest
Your "add a command" skill should ADD a test here for every new command. The point is to assert
intended behavior, not just that nothing crashed.