project 04 — ~75 min

Give Claude Code a definition of done it can't skip

How to keep a codebase legible to its agent

by the end you can:

  • Run the agentic coding loop: plan, edit, run, verify, commit → taught in 2.06
  • Write a definition of done that ties every change to the knowledge base, the decisions log, and a test → taught in 2.06
  • Turn a recurring rule — security review, architecture clean-up, doc refresh — into a skill that runs on a schedule, not from memory → taught in 1.03
  • Turn an unusually good or concerning run into a new skill instead of a note to remember → taught in 1.03
  • Turn a rule that must always hold into a hook rather than a request → taught in 2.03

you need: A terminal · A Claude subscription or Console account · The course repo, or a repo of your own

Claude Code executes an agentic coding loop directly in your terminal: plan, edit, run, verify, and commit, with a model reading and writing files on your local disk. Running an initial session confirms basic tool execution. Maintaining repository stability across two hundred sessions requires deterministic architectural constraints. In this project, you construct repository-level controls: a definition of done that prevents unverified diffs from landing, automated skills that audit security and architectural drift on fixed schedules, and repeatable configurations generated from observed session runs.

This site’s own repository supplies the reference implementation throughout. It implements this operational discipline directly: a rules file, four skills, a knowledge network maintained in the present tense, and an append-only decisions log. We trace the physical mechanism behind each component so you can build these three controls into your own codebase.

step one: install, then read before you write

On macOS, Linux, or WSL, install and confirm the version, then start a session and sign in:

curl -fsSL https://claude.ai/install.sh | bash
claude --version
claude

Windows installers and the complete initial walkthrough (inspecting repository context before writing code, entering plan mode with Shift+Tab, and using the course setup prompt) are documented in claude-code-personal-setup.md and the official quickstart. We begin at the subsequent operational phase: the engineering practices that maintain repository integrity across hundreds of automated sessions.

step two: a definition of done ties every change to the knowledge base, the decisions log, and a test

In the fourth step of the execution loop, verification originates entirely outside the model context window. The harness evaluates deterministic signals, such as an exit code or a failing test assertion, rather than letting the model inspect its own diff. That check confirms only that the implementation functions at the moment of execution. It does not establish whether subsequent developers or automated agents can determine what the code computes or why you selected this implementation over alternatives. Capturing those operational realities requires two additional artifacts.

what a change deposits before it counts as done
1 · verified
a fact the run produced: an exit code, a failing test’s name, a page opened for real
the knowledge doc
the subsystem’s doc now describes the new behavior, present tense
the decisions log
one entry, only when the change chose between real alternatives
2 · commit
code, doc, and the decision (when there is one) land together
Three lanes converge on one commit. Drop the middle lane and the repository still runs; it just stops being legible to the next session, agent or human, which has to reread code to recover a decision the previous session already made and threw away.

Define this requirement as a persistent rule that loads into context on every turn, rather than an ad-hoc instruction in a single prompt:

## definition of done: every change, no exceptions
1. the verification command named below, run for real, not read
2. the doc for the subsystem touched now describes the new behavior
3. a decisions-log entry, only if this change chose between real alternatives
4. all three land in the same commit

This block lives in CLAUDE.md. System prompt instructions condition token probabilities at session start, but long execution traces dilute context conditioning, allowing agent loops to bypass prompt-level instructions. This repository reinforces the rule through code boundaries. Two custom skills chain at the conclusion of every session to enforce these conditions: sync-docs, whose description instructs the model to update the knowledge/ documentation after any codebase change prior to commit, and security-final-check, invoked immediately before committing to inspect the full git diff rather than relying on context history. Stating the contract in CLAUDE.md sets the baseline schema; invoking dedicated verification skills prevents the loop from committing unverified diffs when context windows become saturated.

A definition of done requires three artifacts. The test suite verifies that the code executes correctly. The knowledge document defines the current system state. The decisions log records the architectural rationale whenever the implementation selects between concrete trade-offs. Any commit lacking these three records remains incomplete, regardless of test status.

step three: security, architecture, and documentation get their own skills, run on a schedule you set

The vocabulary trigger that routes sync-docs fires only when a task explicitly mentions documentation. A developer rarely prompts for dead code elimination, secrets auditing, or architectural reviews during ordinary feature work, which means those reviews are deferred until an incident occurs. A rule that must run whether or not anyone thinks of it needs a trigger that is a date. Because Claude Code has no internal timer, that schedule lives in an external operational routine: a recurring calendar block, a release checklist, or a scheduled automation workflow. At that scheduled interval, you invoke the routine directly by name. An operational procedure structured around this scheduled cadence is a maintenance skill.

This repository implements two maintenance skills directly. The description for security-final-check defines its evaluation boundary: injection surfaces, secrets, supply chain risks, the static-site trust model, and the bundle budget, evaluated against the actual git diff instead of the conversational trace history. Tool output boundaries apply here as well: payloads returned by an MCP server or external HTTP fetch represent unvalidated external data, and the security audit verifies whether downstream consumers preserve strict schema validation. The sync-docs skill executes documentation updates on every commit instead of waiting for a calendar interval. This per-commit check remains computationally lightweight because the changed file set is small. In a repository adopting this discipline for the first time, run documentation audits as scheduled passes over the entire knowledge tree, because architectural drift accumulates fastest in untouched legacy directories.

The third pattern, architectural clean-up, is not yet automated on a recurring schedule in this repository. Technical documentation must reflect the actual system state. To implement this pattern as a maintenance skill, configure the skill to parse your documented dependency graph (this repository maintains one in knowledge/index.md) and direct it to report three conditions without altering files: documentation describing mechanisms absent from the codebase, orphaned files missing from the dependency graph, and conflicting formatting or architectural conventions across modules. Architectural decisions remain your responsibility; the maintenance skill’s role is to surface discrepancies deterministically before runtime errors reveal them.

step four: turn what the agent does well or badly into a new skill, not a note to remember

Every new session initializes with an empty context window; no state carries across process restarts except what resides on disk in the repository. This constraint applies to developer feedback just as it does to model inference. An execution trace that resolves a task through an optimal sequence, or one that introduces an architectural violation, exists only in transient process memory unless you capture it as an executable repository artifact.

Reproducing an effective trace requires a custom skill. Name the skill after the concrete operation, and write its description using the exact phrasing from your task prompt. Claude Code invokes the skill by routing on the description against your input text, so the trigger must use authentic operational language rather than generalized summaries. The body of the skill codifies the verified terminal commands and edit sequences executed during that session, parameterized for reuse.

Mitigating an undesirable trace requires code rather than a prompt. When a constraint must hold without exception, you write a hook, a script Claude Code runs before a tool call to validate the operation and halt execution if the check fails. This repository guards environment files against automated modification using a hook configured in .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "bash .claude/hooks/guard-env.sh" }
        ]
      }
    ]
  }
}

Before executing an edit or file write, Claude Code passes the tool invocation payload as JSON to standard input. The script parses the target file path and rejects any target matching .env:

#!/usr/bin/env bash
path=$(jq -r '.tool_input.file_path // empty')
case "$path" in
  *.env|*/.env|*.env.*) echo "blocked: $path is edited by hand only" >&2; exit 2 ;;
esac
exit 0

Exit code two halts tool execution and returns standard error directly to the session. The agent can prompt you to update the environment variables, but the hook prevents automated modification. A line in CLAUDE.md asks the model to avoid editing the file; a hook enforces the rule in code.

the triggerwhat you add
the agent gets a convention or command wrong twicea line in CLAUDE.md
a run is unusually good and you want it repeated exactlya skill named for the action, described in the words you praised it with
a run does something concerning, oncea skill whose body states the constraint explicitly
a run does something concerning, and asking has not been enougha hook that blocks it
you keep copying data from a system the agent cannot seean MCP server
a side task floods the conversation with outputa subagent, with its own window
a second repository needs the same setupa plugin

step five: memory is the repository, not the chat

Every session initializes with a cleared context window, which is the constraint every memory the agent has must work around. Two distinct mechanisms persist state across session resets. The first is CLAUDE.md, which contains operator-defined constraints, including the definition-of-done rules established in step two. Persisting these criteria on disk ensures they remain active after context compaction. The second is auto memory, a directory of markdown files stored at ~/.claude/projects/<project>/memory/. This store logs corrections and confirmed preferences, reading them via an index file at initialization. Run /context in the terminal to inspect the active token allocation, or run /memory to view and edit stored entries. When a previously followed instruction degrades across turns, the root cause is predictable: the instruction existed solely in conversational context, which does not survive session boundaries.

equip yourself with the materials

  1. A starter rules file, the guard hook, a skill skeleton, the definition-of-done checklist, and templates for the three maintenance skills, configuring your own repository in one afternoon: claude-code-personal-setup.md.
  2. Templates for the four instruments, extracted from the course’s own repo: agentic-coding-starter.md.
  3. The paste-ready setup prompt for the course repo: melchizedek-agent-setup.md.
  4. The module: AI builds the feature. The reference documentation is at code.claude.com/docs.

apply it to your own ecosystem

Apply these structural constraints to your primary codebase:

  1. Write the definition-of-done rule into CLAUDE.md: require an external verification command executed against actual test suites, an updated knowledge doc, and an entry in the decisions log whenever an implementation selects between concrete alternatives.
  2. Select one maintenance audit (security review, architectural verification, or documentation refresh) and implement it as a skill invoked explicitly by name. Execute it manually against your repository to verify output quality before adding it to a recurring schedule.
  3. Identify one session run from the past week that produced an optimal implementation, and one that failed or drifted. Write a skill to codify the successful workflow. Implement a lifecycle hook for the failure mode to block unauthorized tool invocations programmatically.
  4. On your next feature implementation, execute the agentic loop end to end. Audit the resulting artifacts upon completion: updated documentation, a recorded architectural decision if alternatives were evaluated, and any newly extracted skill definitions.

Run an identical feature workflow a month later and audit the generated artifacts. The model weights remain identical, as session interactions do not alter static parameters. The difference in operational reliability comes entirely from repository-level constraints and scheduled maintenance gates.