Week 4 studio
This 90-minute studio is individual work with a written alternative. Use a disposable
copy of your project repository. Do not place credentials, employer data or private
material in it. The commands below use only ordinary git and python.
Studio sequence
| Minutes | Activity | Evidence to keep |
|---|---|---|
| 0–15 | Name one failure an agent could cause in your repository | failure and the rule that prevents it |
| 15–30 | Write and review AGENTS.md |
instruction file and one peer question |
| 30–55 | Install the hook and make it block a bad commit | blocked.txt and the nonzero exit |
| 55–70 | Fix the change and commit it | passed.txt and git show --stat |
| 70–85 | Specify one subagent role and inspect its hand-back | role contract and checked hand-back |
| 85–90 | Decide what to accept or narrow | one decision line with evidence |
Keyboard-only editing and a text record provide the same outputs. A partner may read your rule, but each student makes the decision and keeps their own records.
1. Write the instruction file
From the root of a disposable checkout, create AGENTS.md:
cat > AGENTS.md <<'__INSTRUCTIONS__'
# Repository instructions
- Scope: Python files under `src/`; keep public names stable.
- Before editing: read the target function and its tests; name both in your note.
- After editing: run `python -m pytest tests -q` when the repository has tests.
- Stop: do not change lockfiles or files outside this checkout for this task.
__INSTRUCTIONS__
Replace the paths and command with ones that exist in your repository. Under the file,
write a four-row table in instruction-review.md: each rule, the failure it prevents,
and the evidence a reviewer could inspect. Mark any rule that is only a request; an
instruction file alone cannot enforce it.
2. Install a small hook gate
First, from this course checkout, copy the course-written hook to a temporary path. Keep the same shell open while you work in your disposable project checkout:
HOOK_SOURCE="$(mktemp)"
cp lectures/week-04/example/pre_commit.py "$HOOK_SOURCE"
From the root of a disposable project checkout, make a directory if the project has no
src/:
mkdir -p week04-studio-hook/src
cp "$HOOK_SOURCE" week04-studio-hook/pre_commit.py
cd week04-studio-hook
git init -q
git config user.name "Week 4 practice"
git config user.email "week4@example.edu"
cat > .git/hooks/pre-commit <<'__HOOK__'
#!/usr/bin/env python3
import json
import subprocess
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from pre_commit import run
paths = subprocess.check_output(
["git", "diff", "--cached", "--name-only"], text=True
).splitlines()
event = {"event": "before_commit", "paths": paths}
raise SystemExit(run([json.dumps(event)]))
__HOOK__
chmod +x .git/hooks/pre-commit
The copied hook is course-written teaching code. Read it before using it. It checks staged paths and returns 2 for a protected path or an unused import; it does not execute the staged file.
Create the intentionally bad change and capture the failed attempt:
printf 'import json\n\nvalue = 1\n' > src/report.py
git add src/report.py
status=0
git commit -m "practice: blocked import" > blocked.txt 2>&1 || status=$?
cat blocked.txt
echo "exit status: $status"
[ "$status" -ne 0 ]
The command must leave the commit uncreated and blocked.txt must contain the hook's
finding. If it commits, stop and inspect the wrapper before proceeding; do not rewrite the
record to make it look blocked.
Now fix the violation and capture the passing run:
printf 'value = 1\n' > src/report.py
git add src/report.py
git commit -m "practice: pass the gate" > passed.txt 2>&1
cat passed.txt
grep -F "PASS: no protected file" passed.txt
git show --stat --oneline HEAD
Keep blocked.txt, passed.txt, and the commit hash in hook-record.md. Explain that
the hook proves this staged-path check ran; it does not prove the Python behavior is
correct. Run the repository's focused test separately when one exists.
3. Give a subagent a role
Write role-contract.md with exactly one role. This is a prompt and review exercise; you
may use your coding agent directly, but do not give it credentials or an unrestricted
command tool.
Role: researcher
Task: locate the function that parses one report and its callers.
Allowed tools: read files, search text, run one named read-only test.
Forbidden: edits, network, dependency installation, commits.
Hand-back: research.md with file/function references, the test command and two open questions.
Stop condition: stop if the parser is generated or the named test is absent.
Ask for the hand-back using that role contract. Open every cited file and run the named
read-only check yourself. In role-review.md, mark each claim confirmed, refuted
or cannot tell, with the location or output that supports the mark. If you continue to
an implementer role, pass only role-contract.md, research.md and the named files; record
its diff and test output separately. A role name without an allowlist and hand-back is not
a boundary.
4. Decision line
End studio-record.md with one line:
Decision: accept | narrow | recheck | stop — evidence: blocked.txt, passed.txt, and role-review.md
Choose the word that matches your evidence. A clean hook run can support accepting the staged-path invariant; it cannot support accepting untested application behavior.