|
|
|
@@ -56,22 +56,31 @@ That's fine when *you* are the only one standing on the floor. It falls apart th
|
|
|
|
|
two things happening at once. Watch it break:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Agent A is mid-change on a feature branch — uncommitted edits in cli.py
|
|
|
|
|
# Agent A added a `clear` command and committed it on its own branch:
|
|
|
|
|
git switch -c feature/clear
|
|
|
|
|
# ...agent A edits cli.py, hasn't committed...
|
|
|
|
|
# ...agent A edits the usage line in cli.py to add `clear`...
|
|
|
|
|
git commit -am "Add clear command"
|
|
|
|
|
|
|
|
|
|
# You want Agent B to start a different job, so you try to switch:
|
|
|
|
|
# You start Agent B on a fresh branch off main; it begins editing the SAME
|
|
|
|
|
# usage line to add `count`, and hasn't committed:
|
|
|
|
|
git switch main
|
|
|
|
|
git switch -c feature/count
|
|
|
|
|
# ...agent B edits cli.py, hasn't committed...
|
|
|
|
|
|
|
|
|
|
# You try to hop the working directory back to Agent A's branch to check on it:
|
|
|
|
|
git switch feature/clear
|
|
|
|
|
# error: Your local changes to the following files would be overwritten by checkout:
|
|
|
|
|
# cli.py
|
|
|
|
|
# Please commit your changes or stash them before you switch branches.
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Git stops you — correctly. But now you're stuck choosing between bad options:
|
|
|
|
|
Git stops you — correctly. Switching to `feature/clear` would overwrite Agent B's uncommitted edits
|
|
|
|
|
to `cli.py` with Agent A's committed version of those same lines, so Git refuses rather than silently
|
|
|
|
|
destroy the work. But now you're stuck choosing between bad options:
|
|
|
|
|
|
|
|
|
|
- **Commit half-finished work** just to get it out of the way (pollutes history, and Agent A's job
|
|
|
|
|
isn't done).
|
|
|
|
|
- **Stash it** (now Agent A's context lives in a stash you have to remember to pop, and Agent A — a
|
|
|
|
|
- **Commit half-finished work** just to get it out of the way (pollutes history, and Agent B's
|
|
|
|
|
`count` command isn't done).
|
|
|
|
|
- **Stash it** (now Agent B's context lives in a stash you have to remember to pop, and Agent B — a
|
|
|
|
|
long-running session that thinks its files are right there — is now editing files that silently
|
|
|
|
|
changed under it).
|
|
|
|
|
- **Run both agents on the same branch in the same folder** — and watch them overwrite each other's
|
|
|
|
@@ -220,23 +229,40 @@ collide. Then you'll merge both back and clean up.
|
|
|
|
|
|
|
|
|
|
### Part A — Feel the collision (1 minute)
|
|
|
|
|
|
|
|
|
|
Before fixing it, reproduce the bottleneck from "Where branches alone run out." In your `tasks-app`:
|
|
|
|
|
Before fixing it, reproduce the bottleneck from "Where branches alone run out." The wall only appears
|
|
|
|
|
when both branches touch the **same line** of `cli.py` — one committed, one not — so we make each
|
|
|
|
|
branch edit the usage line. (The `sed … > tmp && mv` is just a portable, copy-pasteable stand-in for
|
|
|
|
|
the edit an agent would make.) In your `tasks-app`:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd ~/workflow-course/tasks-app
|
|
|
|
|
git switch -c feature/scratch
|
|
|
|
|
# make a fake uncommitted edit so the working dir is dirty:
|
|
|
|
|
echo "# scratch" >> cli.py
|
|
|
|
|
git switch -c feature/other
|
|
|
|
|
|
|
|
|
|
# Agent A's branch: add `clear` to the usage line and commit it.
|
|
|
|
|
git switch -c feature/clear
|
|
|
|
|
sed 's/done <index>/done <index> | clear/' cli.py > cli.tmp && mv cli.tmp cli.py
|
|
|
|
|
git commit -am "Add clear command (demo)"
|
|
|
|
|
|
|
|
|
|
# Agent B's branch, off main: start adding `count` to the SAME line — leave it uncommitted.
|
|
|
|
|
git switch main
|
|
|
|
|
git switch -c feature/count
|
|
|
|
|
sed 's/done <index>/done <index> | count/' cli.py > cli.tmp && mv cli.tmp cli.py
|
|
|
|
|
|
|
|
|
|
# Try to hop the working directory back to Agent A's branch:
|
|
|
|
|
git switch feature/clear
|
|
|
|
|
# error: Your local changes to the following files would be overwritten by checkout:
|
|
|
|
|
# cli.py
|
|
|
|
|
# Please commit your changes or stash them before you switch branches.
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Git refuses — it won't move you to another branch with uncommitted changes in the way. *That* is the
|
|
|
|
|
wall. Clean up before continuing:
|
|
|
|
|
Git refuses — moving the one working directory to `feature/clear` would overwrite Agent B's
|
|
|
|
|
uncommitted edit with `feature/clear`'s committed version of that line. *That* is the wall: one
|
|
|
|
|
directory can't hold two agents' in-progress work at once. These two branches existed only to feel
|
|
|
|
|
the collision, so clean them up before continuing:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
git restore cli.py
|
|
|
|
|
git restore cli.py # drop Agent B's uncommitted edit
|
|
|
|
|
git switch main
|
|
|
|
|
git branch -D feature/scratch feature/other
|
|
|
|
|
git branch -D feature/clear feature/count # throw away the demo branches
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Part B — Create two worktrees
|
|
|
|
@@ -269,16 +295,19 @@ This is the part to actually *do simultaneously*, not one then the other.
|
|
|
|
|
`lab/agent-a-prompt.md` — *add a `clear` command that removes all tasks.*
|
|
|
|
|
2. Open `~/workflow-course/tasks-app-count` in a **second** editor/AI session. Give it the prompt in
|
|
|
|
|
`lab/agent-b-prompt.md` — *add a `count` command that prints the number of pending tasks.*
|
|
|
|
|
3. Let both work at the same time. While they run, prove the isolation from a third terminal:
|
|
|
|
|
3. Let both work at the same time. While they run, prove the isolation from a third terminal — but
|
|
|
|
|
use commands that **already exist**. (`clear` and `count` don't yet; the agents are still writing
|
|
|
|
|
them.) Give each worktree its own task and list it:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd ~/workflow-course/tasks-app-clear && python cli.py clear # agent A's feature
|
|
|
|
|
cd ~/workflow-course/tasks-app-count && python cli.py count # agent B's feature
|
|
|
|
|
cd ~/workflow-course/tasks-app-clear && python cli.py add "from worktree A" && python cli.py list
|
|
|
|
|
cd ~/workflow-course/tasks-app-count && python cli.py add "from worktree B" && python cli.py list
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Each app runs its own command in its own folder. Note that each worktree has its **own**
|
|
|
|
|
`tasks.json` (it's gitignored runtime state, not shared history) — so the two running apps don't
|
|
|
|
|
even share data. Total isolation.
|
|
|
|
|
Each `list` shows only its own task — worktree A never sees "from worktree B" and vice versa. Each
|
|
|
|
|
worktree has its **own** `tasks.json` (gitignored runtime state, not shared history), so the two
|
|
|
|
|
running apps don't even share data. Separate files, separate state, while both agents work. Total
|
|
|
|
|
isolation.
|
|
|
|
|
|
|
|
|
|
4. In each worktree, commit the agent's work on its own branch:
|
|
|
|
|
|
|
|
|
@@ -289,6 +318,16 @@ This is the part to actually *do simultaneously*, not one then the other.
|
|
|
|
|
|
|
|
|
|
Two agents, two commits, two branches — neither ever saw the other's files.
|
|
|
|
|
|
|
|
|
|
5. *Now* the new commands exist — run each in its own worktree to watch it work:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd ~/workflow-course/tasks-app-clear && python cli.py clear # agent A's new command
|
|
|
|
|
cd ~/workflow-course/tasks-app-count && python cli.py count # agent B's new command
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`count` reports only worktree B's task — the one you added in step 3 — because B's `tasks.json` is
|
|
|
|
|
the only state it can see. The isolation, one last time.
|
|
|
|
|
|
|
|
|
|
### Part D — Merge back and clean up
|
|
|
|
|
|
|
|
|
|
Bring both features home to `main` in your original worktree:
|
|
|
|
@@ -354,8 +393,8 @@ Worktrees are sharp tools. The honest caveats:
|
|
|
|
|
|
|
|
|
|
**You're done when:**
|
|
|
|
|
|
|
|
|
|
- `git worktree list` showed three entries at once, and you ran a different command of the
|
|
|
|
|
`tasks-app` from two different worktree folders.
|
|
|
|
|
- `git worktree list` showed three entries at once, and you ran the `tasks-app` from two different
|
|
|
|
|
worktree folders — adding a different task in each and watching each keep its own `tasks.json`.
|
|
|
|
|
- You ran two AI sessions in parallel — each in its own worktree on its own branch — and confirmed
|
|
|
|
|
neither touched the other's files (different folders, different `tasks.json`, different branch).
|
|
|
|
|
- You merged both feature branches back into `main` (resolving a conflict if one appeared) and the
|
|
|
|
|