Fix Module 25 command injection + lab integrity (#24–#27) (#54)

Co-authored-by: claude <claude@jpaul.io>
Co-committed-by: claude <claude@jpaul.io>
This commit was merged in pull request #54.
This commit is contained in:
2026-06-22 14:37:19 -04:00
committed by Claude (agent)
parent 2684095e2f
commit b061a9da14
4 changed files with 65 additions and 9 deletions
+16 -3
View File
@@ -228,9 +228,21 @@ shows how the exact same flow runs on a real forge as a triggered/scheduled job.
don't have one wired up, the script's `--simulate` mode demonstrates every gate and loop
deterministically with no agent at all — do that first regardless.
> **What `--simulate` actually does — read this before Part A.** To stay deterministic and never
> touch your real `cli.py` / `tasks.py`, `--simulate` does **not** implement
> `issue-delete-command.md`. Instead it writes a small, self-contained stand-in (`agent_demo.py` with
> a `discount()` function, plus its test) and runs the *real* gate (ruff + pytest) against that. So
> Parts AC exercise the machinery and the gates — not the delete feature itself. The issue is only
> truly implemented in **Part D**, with a live agent. When you review the simulated diff you'll see
> the `discount()` demo, not a `delete` command; that's expected, and it's why the simulation is
> reproducible enough to teach with.
### Part A — See the gate catch a bad change (simulated, no agent needed)
Copy `agent_runner.py` and `issue-delete-command.md` into your `tasks-app` folder. Then, from a clean
Copy `agent_runner.py` and `issue-delete-command.md` into your `tasks-app` folder, along with this
module's `lab/.gitignore` (append its lines to the `.gitignore` you already have from Module 2 rather
than overwriting it). Commit that `.gitignore` first — it keeps the lab scaffolding and Python caches
out of the agent's `git add -A`, so the change you review in Part B is clean. Then, from a clean
branch:
```bash
@@ -254,8 +266,9 @@ python agent_runner.py issue-to-pr issue-delete-command.md --simulate good
This time the planted change is correct. The gate passes, the script commits to the branch and prints
the diff for review plus the exact `git push` / open-PR command. **It does not merge.** Open the diff
and review it with the Module 10 checklist — you are the human gate, and that step doesn't go away
just because an agent did the typing.
and review it with the Module 10 checklist. Remember (from the note above) that the simulated diff is
the self-contained `discount()` stand-in, not a `delete` command — but the review *motion* is the real
lesson: you are the human gate, and that step doesn't go away just because an agent did the typing.
### Part C — Run the self-healing loop