Project memory for the coding agent working in this repo. The human-facing
overview is in README.md; this file holds the procedural detail.
A loop run once per course: course materials → build-ready spec.md → a recorded
build → two evals → iterate. The goal is to test whether course materials yield
specs that produce apps which (a) follow the spec and (b) stay faithful to the
course.
Launch the session once at the repo root and stay there. Within this one session your working directory moves:
- repo root →
/new-course. courses/<name>/→/generate-spec,/prepare-build,/extract-build-log,/eval-spec-vs-build,/eval-materials-vs-build.cdhere before running them; they act on the current course. Relative paths below are from this folder.courses/<name>/builds/run-NN/→ the actual app development (install deps, run services, optional app-levelgit init).cdhere to build.
Completing a build in the same session that started it keeps the breadcrumb
at evals/run-NN/.session accurate; /extract-build-log reads that breadcrumb
to find the right transcript. Cross-session continuation is possible but not yet
supported automatically — see "Building" below.
/new-course <name>— run from the repo root. Copiestemplates/course/tocourses/<name>/. Does NOT generate the spec. After scaffolding, point the user at https://course-context-lab.vercel.app to download notebooks and transcripts manually, and remind them that dragging files from Finder into the terminal pastes the absolute paths so the agent cancpthem in cheaply. The agent does NOT WebFetch from that URL — it's a manual user step./generate-spec— readsmaterials/notebooks/andmaterials/transcripts/, follows.claude/skills/generate-spec/references/spec-generation-guide.md, and writesspec.md./prepare-build— the expected, explicit way to start a build run; allocates the run and drops a session breadcrumb atevals/run-NN/.session(see below). It will also fire on its own if the user just starts building againstspec.md, but treat the explicit call as the norm./extract-build-log <run-NN>— slices the build conversation out of Claude Code's session transcript and writesevals/run-NN/session-log.md. Run when the build is in a state worth capturing. Re-runnable with different bookends via--until="<phrase>"./eval-spec-vs-build <run-NN>— compares the per-run spec snapshotevals/run-NN/spec.mdagainstbuilds/run-NN/; writesevals/run-NN/spec-vs-build.md. Spec fidelity only. Requires arun-NN./eval-materials-vs-build <run-NN>— comparesmaterials/againstbuilds/run-NN/; writesevals/run-NN/materials-vs-build.md. Course alignment only. Requires arun-NN.
If the user runs either eval without naming a run, do NOT guess and do NOT pick the
latest — list the runs in builds/ and ask which one.
Do not swap the two evals: spec-vs-build asks "did it follow spec.md",
materials-vs-build asks "is it faithful to the course". Different reference,
different question.
Recording is post-hoc: Claude Code already writes every turn into
~/.claude/projects/<slug>/<session>.jsonl, and /extract-build-log slices that
transcript on demand. There is no Stop hook, no .active-run pointer, no
build-complete marker. Skipping /extract-build-log means the conversation is
still preserved in Claude Code's transcript directory; the eval skills judge the
built artifact, not the conversation, so they don't depend on the log.
While cwd is inside courses/<name>/builds/run-NN/, the build agent must read
only spec.md (the working copy in the build folder, or its snapshot at
evals/run-NN/spec.md) and the build folder's own contents. Do not read
../materials/, ../../courses/<name>/materials/, or any course materials.
The two-eval design depends on this. /eval-spec-vs-build asks "did the build
follow spec.md?", /eval-materials-vs-build asks "is the build faithful to
the course?". If the agent saw the materials during the build, the second eval
measures the agent's recall, not the spec's fidelity — the experiment collapses
silently.
Three layers reinforce this beyond the rule itself:
/prepare-buildcopiesspec.mdintobuilds/run-NN/, so the build folder is self-sufficient and the agent has no reason to navigate up.- A stateless
PreToolUsehook (.claude/hooks/no-materials-during-build.sh) blocks any tool call from inside abuilds/run-*/cwd whose target path matchesmaterials/. The agent literally cannot read materials there. /extract-build-logscans the recorded transcript afterwards and surfaces a "WARNING: N reads touched materials/" header insession-log.mdif the hook was somehow bypassed. Contamination is recorded, not silent.
Writing constraint: any document the build agent reads (this CLAUDE.md, every
SKILL.md) must stay course-agnostic. Mentioning the path pattern materials/ for
the prohibition is safe — that's meta-knowledge about the experiment, not course
content. Describing what specific courses contain or teach is NOT safe — that
would leak course content into the docs themselves.
- The user normally calls
/prepare-buildto begin. If they instead just start building againstspec.md, treat that as the trigger too. - The human never creates run folders.
/prepare-builddoes, as its first action:- Allocate the next run: scan
builds/for the highestrun-NN, add one (run-01if empty), zero-padded. - Create
builds/run-NN/— this folder holds the app only. - Snapshot the spec: copy the course's
spec.mdtoevals/run-NN/spec.md. The spec eval reads this frozen copy, so the run is judged against the spec it was actually built from even ifspec.mdis regenerated later. - Drop the session breadcrumb at
evals/run-NN/.sessioncontaining the absolute path to the current Claude Code transcript JSONL. Write-once, never updated, never read by anything except/extract-build-log. - Announce, e.g. "Run 03 — building in
builds/run-03/. When the build is in a state worth capturing, run/extract-build-log run-03," andcdintobuilds/run-NN/to develop the app there.
- Allocate the next run: scan
- After the build is in a satisfactory state — or any time you want a snapshot —
run
/extract-build-log run-NN. It reads the breadcrumb, opens the transcript JSONL, slices between an opening bookend (the/prepare-buildannouncement for this run) and a closing bookend (default: a fuzzy diagram/structure phrase; override with--until="<phrase>"; falls back to end-of-transcript if no closing bookend is found), and writesevals/run-NN/session-log.md. Idempotent — re-run with different bookends to re-slice. - Cross-session caveat: the breadcrumb points at the transcript that existed at allocation time. If a build is started in session A but continued in session B, only session A's portion is captured. Stay in one session per build for now.
builds/run-NN/— the built app, only. Clean; may have its own git. This repo gitignoresbuilds/.evals/run-NN/— everything recorded or judged about the run:.session(the breadcrumb dropped at allocation, hidden),spec.md(the snapshot taken at allocation),session-log.md(produced by/extract-build-log),spec-vs-build.md,materials-vs-build.md.evals/run-NN/is generated to match the build. The run number is the join key between a build and its evaluation — keep them aligned. Evals require an explicitrun-NN; if none is given, list the runs inbuilds/and ask — never default.
run-NN is per course (run-01, run-02, …). Every new build is a new run —
even with the same spec.md — so runs and their evals can be compared.
spec-generation-guide.md— the core lever; defines what a build-ready spec must contain. Authored iteratively against eval feedback.extract-build-log/scripts/extract.pyrendering — v1 keeps assistant tool-call metadata as one-line previews and suppresses tool-result outputs. Revisit if rendered logs feel thin once we have a real build to look at.