De-slop: remove every em-dash + banned words across all modules + capstone (#94)
Sync course wiki / sync-wiki (push) Successful in 4s
Sync course wiki / sync-wiki (push) Successful in 4s
Co-authored-by: claude <claude@jpaul.io> Co-committed-by: claude <claude@jpaul.io>
This commit was merged in pull request #94.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Module 11 — Collaboration: Humans and Agents on One Repo
|
||||
# Module 11: Collaboration: Humans and Agents on One Repo
|
||||
|
||||
> **You now have every piece: issues, branches, PRs, review. This module wires them into one loop,
|
||||
> and points out that half your "teammates" might not be human.** Once the loop runs the same way no
|
||||
@@ -10,14 +10,14 @@
|
||||
|
||||
This is the synthesis module for Unit 2's collaboration arc. It assumes the whole chain up to here:
|
||||
|
||||
- **Module 2** — commits as checkpoints, and `git diff`/`git log` as the record everyone reads.
|
||||
- **Module 6** — branches as isolated sandboxes; you make changes off `main`, not on it.
|
||||
- **Module 7** — worktrees, so more than one branch (and more than one agent) can be live at once
|
||||
- **Module 2:** commits as checkpoints, and `git diff`/`git log` as the record everyone reads.
|
||||
- **Module 6:** branches as isolated sandboxes; you make changes off `main`, not on it.
|
||||
- **Module 7:** worktrees, so more than one branch (and more than one agent) can be live at once
|
||||
without stepping on each other.
|
||||
- **Module 8** — a remote on a git host (GitHub the default; a self-hosted forge if you took that
|
||||
- **Module 8:** a remote on a git host (GitHub the default; a self-hosted forge if you took that
|
||||
track), so there's a shared copy to collaborate around.
|
||||
- **Module 9** — issues: the task layer that says *what* needs doing and *who* (human or agent) owns it.
|
||||
- **Module 10** — pull/merge requests and the skill of reviewing a diff you didn't write.
|
||||
- **Module 9:** issues: the task layer that says *what* needs doing and *who* (human or agent) owns it.
|
||||
- **Module 10:** pull/merge requests and the skill of reviewing a diff you didn't write.
|
||||
|
||||
Each of those taught one move. This module is the assembled motion. If you're missing one, the loop
|
||||
still works, but a step will feel like a black box, so go back and fill it in.
|
||||
@@ -28,15 +28,15 @@ still works, but a step will feel like a black box, so go back and fill it in.
|
||||
|
||||
By the end of this module you can:
|
||||
|
||||
1. Run the full collaboration loop end to end — issue → branch → implementation → PR → review →
|
||||
merge → issue auto-closed — and explain why each step exists.
|
||||
1. Run the full collaboration loop end to end (issue → branch → implementation → PR → review →
|
||||
merge → issue auto-closed) and explain why each step exists.
|
||||
2. Link a PR to an issue so the merge closes the issue automatically, and explain when that does and
|
||||
doesn't fire.
|
||||
3. Decide correctly between a **branch** and a **fork** based on whether you have push access.
|
||||
4. Reason about **who's allowed to push**: roles, protected branches, and why "never commit to
|
||||
`main`" stops being a personal habit and becomes an enforced rule.
|
||||
5. Treat an agent as a contributor — give it a branch, route an issue to it, review its PR on the
|
||||
same gate you'd use for a human — and know where a human has to stay in the loop.
|
||||
5. Treat an agent as a contributor (give it a branch, route an issue to it, review its PR on the
|
||||
same gate you'd use for a human) and know where a human has to stay in the loop.
|
||||
|
||||
---
|
||||
|
||||
@@ -47,7 +47,7 @@ By the end of this module you can:
|
||||
Module 2 gave you the **inner loop**: edit, `git diff`, commit, repeat. That loop lives on your disk
|
||||
and is yours alone. It's how *you* (or your agent) make progress in a working session.
|
||||
|
||||
This module is the **outer loop** — the one the *team* sees:
|
||||
This module is the **outer loop**, the one the *team* sees:
|
||||
|
||||
```
|
||||
issue → branch → implementation → pull request → review → merge → issue closed
|
||||
@@ -68,13 +68,13 @@ the module, and we'll come back to it.
|
||||
|
||||
### The loop, step by step
|
||||
|
||||
**1 — The issue (Module 9) is the contract.** Before any code, there's a statement of intent: a
|
||||
**1. The issue (Module 9) is the contract.** Before any code, there's a statement of intent: a
|
||||
title, a description of the desired behavior, maybe acceptance criteria. It has a number (`#42`) that
|
||||
the rest of the loop will reference. The issue exists so that "what we're doing and why" lives
|
||||
somewhere durable and shared, not in one person's head or one chat session that'll evaporate
|
||||
(Module 1, Seam 2). Assign it to whoever's taking it: a person, or an agent.
|
||||
|
||||
**2 — The branch (Module 6) is the workspace.** You never implement on `main`. You cut a branch
|
||||
**2. The branch (Module 6) is the workspace.** You never implement on `main`. You cut a branch
|
||||
named for the work. Convention is something traceable like `42-clear-done-command` (the issue
|
||||
number plus a slug). The name matters more than it looks: months later, `git branch` and the host's
|
||||
branch list become a map of "what's in flight," and the issue number ties each branch back to its
|
||||
@@ -85,7 +85,7 @@ git switch -c 42-clear-done-command # branch off main and switch to it
|
||||
# Switched to a new branch '42-clear-done-command'
|
||||
```
|
||||
|
||||
**3 — Implementation is the inner loop (Module 2).** This is where the actual editing happens —
|
||||
**3. Implementation is the inner loop (Module 2).** This is where the actual editing happens:
|
||||
you, or an agent, making commits on the branch. Nothing here is new; it's the edit/diff/commit
|
||||
rhythm you already have. The branch keeps it isolated, so however bold the change, `main` is
|
||||
untouched until the loop says otherwise.
|
||||
@@ -95,22 +95,22 @@ git push -u origin 42-clear-done-command # publish the branch so others (and t
|
||||
# branch '42-clear-done-command' set up to track 'origin/42-clear-done-command'.
|
||||
```
|
||||
|
||||
**4 — The pull request (Module 10) makes it reviewable.** Opening a PR says "this branch is ready
|
||||
**4. The pull request (Module 10) makes it reviewable.** Opening a PR says "this branch is ready
|
||||
to be considered for `main`." It bundles the diff, a description, and a discussion thread into one
|
||||
reviewable unit. Crucially, **this is where you link back to the issue** (next section) so the loop
|
||||
can close itself.
|
||||
|
||||
**5 — Review (Module 10) is the judgment gate.** Someone who isn't the author reads the diff for
|
||||
**5. Review (Module 10) is the judgment gate.** Someone who isn't the author reads the diff for
|
||||
correctness *and plausibility*, the skill Module 10 is built around. They approve, request changes,
|
||||
or comment. For AI-generated diffs this gate is doing more work than it used to: the code compiles,
|
||||
reads cleanly, and is still wrong in a way only review catches.
|
||||
|
||||
**6 — Merge is the commitment.** Approved, the PR merges into `main`. Hosts offer a couple of merge
|
||||
**6. Merge is the commitment.** Approved, the PR merges into `main`. Hosts offer a couple of merge
|
||||
styles, a squash or a merge commit; your team picks one and the effect is the same: the branch's work
|
||||
is now part of the shared trunk. (You'll also see a *rebase-merge* option; it rewrites history and is
|
||||
out of scope here.) Delete the branch after; its job is done and its name lives on in the merge.
|
||||
|
||||
**7 — The issue closes — ideally by itself.** If you linked the PR correctly, merging closes the
|
||||
**7. The issue closes, ideally by itself.** If you linked the PR correctly, merging closes the
|
||||
issue automatically. The receipt is written without anyone touching the issue. That's the satisfying
|
||||
*click* of the whole loop landing, and it's the concrete thing the lab makes you feel.
|
||||
|
||||
@@ -123,7 +123,7 @@ The mechanic that makes step 7 free: put a **closing keyword** in the PR descrip
|
||||
Closes #42
|
||||
```
|
||||
|
||||
`Closes`, `Fixes`, and `Resolves` (and their variants — `close/closed`, `fix/fixed`,
|
||||
`Closes`, `Fixes`, and `Resolves` (and their variants `close/closed`, `fix/fixed`,
|
||||
`resolve/resolved`) all work on the major hosts. When the PR merges **into the default branch**, the
|
||||
host closes the referenced issue and cross-links the two so each shows the other. One line in the PR
|
||||
body buys you a self-closing loop and a permanent trail from "why we did this" (issue) to "what we
|
||||
@@ -179,9 +179,9 @@ have for production systems.
|
||||
branch) as protected, and the host then *refuses* direct pushes to it. The only way in is a PR. You
|
||||
can layer rules on top:
|
||||
|
||||
- **Require a pull request** — no direct pushes, full stop. The loop is mandatory, not optional.
|
||||
- **Require a review approval** — at least one non-author approval before merge is allowed.
|
||||
- **Restrict who can merge** — only certain roles can click the button.
|
||||
- **Require a pull request:** no direct pushes, full stop. The loop is mandatory, not optional.
|
||||
- **Require a review approval:** at least one non-author approval before merge is allowed.
|
||||
- **Restrict who can merge:** only certain roles can click the button.
|
||||
|
||||
Turning these on converts "we agreed not to push to `main`" into "the server won't let you." For a
|
||||
solo learner this can feel like bureaucracy, but it's exactly the guardrail that makes it safe to add
|
||||
@@ -280,7 +280,7 @@ loop, not the code, is what you're practicing.
|
||||
Starter artifacts are in this module's `lab/`: `issue.md` (the issue to file) and `pr-body.md` (the
|
||||
PR description, including the load-bearing closing keyword).
|
||||
|
||||
### Part A — Set the guardrail (one-time)
|
||||
### Part A: Set the guardrail (one-time)
|
||||
|
||||
Before the loop, make `main` enforce what you've been doing by hand. In your host's web UI, open the
|
||||
repo's branch-protection settings and protect `main` with **"require a pull request before merging."**
|
||||
@@ -304,7 +304,7 @@ was a throwaway to test the guardrail. Its full treatment and its real dangers a
|
||||
If the push went through instead of bouncing, protection isn't on; fix that before continuing. Feeling
|
||||
the server say *no* is the point: "never commit to `main`" is now a rule, not a resolution.
|
||||
|
||||
### Part B — Issue → branch
|
||||
### Part B: Issue → branch
|
||||
|
||||
1. **File the issue.** Create a new issue from `lab/issue.md` (title and body). Note its number; say
|
||||
it's `#42`. This is the contract.
|
||||
@@ -325,7 +325,7 @@ the server say *no* is the point: "never commit to `main`" is now a rule, not a
|
||||
The branch-naming convention (issue number plus a short slug) is the thing to get right here, not
|
||||
the keystrokes.
|
||||
|
||||
### Part C — Implementation (with AI)
|
||||
### Part C: Implementation (with AI)
|
||||
|
||||
3. Point Claude Code at `~/ai-workflow-course/tasks-app` and ask for the feature:
|
||||
|
||||
@@ -345,7 +345,7 @@ the server say *no* is the point: "never commit to `main`" is now a rule, not a
|
||||
```bash
|
||||
python cli.py add "keeper" ; python cli.py add "trash"
|
||||
python cli.py list # note the index shown next to "trash"
|
||||
python cli.py done <trash-index> # use the index "list" just printed — NOT a fixed 1
|
||||
python cli.py done <trash-index> # use the index "list" just printed, NOT a fixed 1
|
||||
python cli.py clear-done # expect it to remove the completed one
|
||||
python cli.py list # "keeper" remains, "trash" is gone
|
||||
```
|
||||
@@ -366,7 +366,7 @@ the server say *no* is the point: "never commit to `main`" is now a rule, not a
|
||||
git show --stat HEAD # only tasks.py and cli.py listed; subject ends "(closes #42)"
|
||||
```
|
||||
|
||||
### Part D — PR → review → merge → auto-close
|
||||
### Part D: PR → review → merge → auto-close
|
||||
|
||||
6. **Open the PR** from your branch into `main`, using `lab/pr-body.md` as the description. Make sure
|
||||
the body contains the closing line with **your** issue number:
|
||||
@@ -376,7 +376,7 @@ the server say *no* is the point: "never commit to `main`" is now a rule, not a
|
||||
```
|
||||
|
||||
7. **Review it.** Open the PR's "Files changed" tab and read the diff *as a reviewer*, not as the
|
||||
author — the Module 10 move. For the full effect, pretend an agent wrote it (in a moment, one
|
||||
author, the Module 10 move. For the full effect, pretend an agent wrote it (in a moment, one
|
||||
will): is the logic where it belongs? Any edge case missed (empty list, nothing done yet)?
|
||||
Approve it.
|
||||
|
||||
@@ -398,10 +398,10 @@ the server say *no* is the point: "never commit to `main`" is now a rule, not a
|
||||
git branch # 42-clear-done-command no longer listed; you're on main
|
||||
```
|
||||
|
||||
### Part E — Now make the contributor an agent
|
||||
### Part E: Now make the contributor an agent
|
||||
|
||||
Run the loop one more time, but this time **let an agent be the contributor for steps 2–6.** File a
|
||||
second issue (e.g. "Add a `pending` command that lists only incomplete tasks" — the `TaskList.pending()`
|
||||
second issue (e.g. "Add a `pending` command that lists only incomplete tasks"; the `TaskList.pending()`
|
||||
method already exists, so this is wiring only).
|
||||
|
||||
**First, a reality check the rest of the lab let you skip.** Two of those steps cross the forge
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<!--
|
||||
Module 11 lab — the issue to file (the "contract" / station 1 of the loop).
|
||||
Module 11 lab: the issue to file (the "contract" / station 1 of the loop).
|
||||
|
||||
Create a new issue on your git host. Paste the line below as the TITLE and everything under
|
||||
"Body" as the issue description. Note the number the host assigns it (e.g. #42) — every later
|
||||
"Body" as the issue description. Note the number the host assigns it (e.g. #42); every later
|
||||
step references it. Assign it to yourself for the first run-through.
|
||||
-->
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Module 11 lab — the pull request description (station 4 of the loop).
|
||||
Module 11 lab: the pull request description (station 4 of the loop).
|
||||
|
||||
Paste this as the body when you open the PR from your branch into main. The "Closes" line is the
|
||||
load-bearing part: replace 42 with YOUR issue number. On merge to the default branch, the host
|
||||
@@ -18,7 +18,7 @@ method in `tasks.py`; `cli.py` just wires up the command and reports how many ta
|
||||
|
||||
- Added a mix of pending and done tasks, ran `clear-done`, confirmed only the done ones were removed
|
||||
and the count printed.
|
||||
- Ran `clear-done` with nothing marked done — removed 0, no crash.
|
||||
- Ran `clear-done` with nothing marked done: removed 0, no crash.
|
||||
|
||||
## Review notes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user