Skip to content

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.