Making the Repository the Single Source of Truth

Read21 min · Plan → Implement → Verify → Evolve · Updated 2026-09-15

You end this lesson with: A repository map the agent can load: what exists, where it lives, what is authoritative.

Chapters

  1. What Belongs on the Map
    01
  2. Knowledge Visibility
    02
  3. Core Concepts
    03
  4. How to Draw a Good Map
    04
  5. Managing Agent State with ACID Principles
    05
  6. Trace It: The 30-Microservice Repo
    06
view

Practice project: Project 02. Make the Agent Read the Project and Pick Up Where It Left Off

Lecture 03. Making the Repository the Single Source of Truth

Illustrative composite. A fintech team's payments-service repo carries an unwritten rule: retries against the /charge endpoint must be idempotent, enforced by a header check added after a duplicate-charge incident years earlier. Everyone who was there remembers why the check exists. Nothing about it lives in the repo, no comment, no doc, no test named after the incident. An agent asked to simplify the retry logic sees a header check with no visible purpose, decides it's dead code, and removes it as part of a routine cleanup. The change passes review, because the reviewer doesn't remember the incident either. Weeks later, a flaky network path starts retrying real charges, and support starts fielding tickets from customers billed twice for the same order. Tracing the regression back to one deleted header check takes longer than writing the original fix ever did. Decide now: whose fault was this, the agent's, the reviewer's, or the rule that was never written down?

This isn't an exaggeration. An agent has only three sources of input: system prompts and task descriptions, file contents from the repository, and tool execution output. Your Slack history, Jira tickets, Confluence pages, and that architecture decision you hashed out with a colleague on Friday afternoon, the agent can't see any of it. It can't "go ask someone" or "search the chat logs." Its entire working world is the repository itself. Everything outside, it knows nothing about.

So the real question is: are you going to give it a map that's good enough?

What Belongs on the Map

OpenAI states this plainly in their harness engineering article: information that doesn't exist in the repo, doesn't exist for the agent. They call this the "repo as spec" principle, the repository itself is the highest-authority specification document.

Anthropic's long-running agents documentation echoes a similar point: persistent state is a necessary condition for long-task continuity, and cross-session knowledge recoverability directly determines task success rates. And this state must exist in the repository, because that's the only stable, reliably accessible storage the agent has.

You might think: "Our team is small, knowledge lives in everyone's heads, and it works fine." True enough, for humans. But if you want to use an agent, you have to accept one fact: the agent can't ask people. Everything it needs to know must be written down, placed somewhere it can find it.

This isn't a "write more documentation" problem, it's a "put decision information in the right place" problem. A 50-line ARCHITECTURE.md sitting in the src/api/ directory is far more useful than a 500-page design document in Confluence that nobody maintains. Proximity matters more than length, because information is only truly useful when it's right at hand the moment you need it.

Knowledge Visibility

diagram
drawing

How do you test whether your map is good enough? Run a "fresh session test": open a brand-new agent session, give it only the repository contents, and see if it can answer five basic questions.

diagram
drawing

If it can't answer, the map has blank spots. Where the map is blank, the agent has to guess, wrong guesses become bugs, excessive guessing wastes context. And every new session has to guess all over again. The cost of guessing is always far higher than the cost of drawing the map properly in the first place.

Core Concepts

  • Knowledge Visibility Gap: The proportion of total project knowledge that's NOT in the repository. The bigger the gap, the higher the agent's failure rate. You can estimate it like this: count all the implicit knowledge about this project that lives in people's heads, then see how much of it actually made it into the repo. The difference is your visibility gap.
  • System of Record: The code repository as the authoritative source for project decisions, architecture constraints, execution state, and verification standards. The repo has the final say, nowhere else counts. If the information "this road is closed" only lives in Old Zhang's head, then every single time you have to ask Old Zhang. Write it in the repo, and nobody has to ask.
  • Fresh Session Test: The five questions from the previous section. How many the agent can answer is how complete your map is.
  • Discovery Cost: How much context budget the agent burns to find a single key piece of information in the repo. The more hidden the information, the higher the discovery cost, and the less budget remains for the actual task. Critical information should be placed where the agent sees it first, not buried ten directory levels deep.
  • Knowledge Decay Rate: The proportion of knowledge entries in the repo that become stale per unit of time. Documentation drifting out of sync with code is the biggest enemy, worse than no documentation at all is documentation that's out of date.
  • ACID Analogy: Applying database transaction principles (Atomicity, Consistency, Isolation, Durability) to agent state management. We'll expand on this below.

How to Draw a Good Map

Use a per-module doc, placed next to the code it governs, when a rule only matters to whoever is already touching that module. Use the root AGENTS.md instead when the rule holds no matter what part of the repo gets touched. Put a rule nowhere, or convert it to a test, when it stopped being true and nobody would miss it.

Where the rule appliesPut it inWhy
Everywhere, regardless of what's touched (e.g. "all endpoints need OAuth")Root AGENTS.md, one of its ≤15 hard constraintsLoaded before anything else; wrong everywhere if the agent misses it
Only when touching one module (e.g. a migration ordering rule)A doc next to that module, src/db/CONSTRAINTS.mdZero discovery cost when relevant, zero weight when not
No longer true, or nobody would notice its absenceNeither, delete it or convert it to a testA stale written rule is worse than no rule; an executable check beats prose everywhere

The four principles below are what applying that split actually looks like, module by module.

Principle 1: Knowledge lives next to code. A rule about API endpoint authentication belongs next to the API code, not buried in a giant global document. Put a short doc in each module directory explaining that module's responsibilities, interfaces, and special constraints. The module directory itself is a natural index, when the agent reaches the code, it also reaches the constraints, no searching required.

Principle 2: Use a standardized entry file. AGENTS.md (or CLAUDE.md) is the agent's "landing page." It doesn't need to contain all information, but it must let the agent quickly answer three questions: "What is this project," "How do I run it," and "How do I verify it." 50,100 lines is enough.

Principle 3: Minimal but complete. Every piece of knowledge should have a clear use case. If removing a rule doesn't affect the agent's decision quality, that rule shouldn't exist. But every question from the fresh session test must have an answer. This is an ongoing balance to maintain, not too much, not too little, just enough.

Principle 4: Update with code. Bind knowledge updates to code changes. The simplest approach: put architecture docs in the corresponding module directory. When you modify code, you naturally notice the doc. After code changes, CI can remind you to check whether the docs need updating.

Concrete repo structure:

project/ ├── AGENTS.md # Entry: project overview, run commands, hard constraints ├── src/ │ ├── api/ │ │ ├── ARCHITECTURE.md # API layer architecture decisions │ │ └── ... │ ├── db/ │ │ ├── CONSTRAINTS.md # Database operation hard constraints │ │ └── ... │ └── ... ├── PROGRESS.md # Current progress: done, in-progress, blocked └── Makefile # Standardized commands: setup, test, lint, check

Managing Agent State with ACID Principles

This analogy comes from database transaction management. You might feel like this is overcomplicating things, but it actually provides a very practical framework:

  • Atomicity: Each "logical operation" (e.g., "add new endpoint and update tests") gets one git commit. If it fails midway, git stash to roll back. All or nothing, no "half done."
  • Consistency: Define "consistent state" verification predicates, all tests pass, lint reports zero errors. The agent runs verification after each operation; inconsistent intermediate states should not be committed. After an operation, the system should be in a verifiably correct state.
  • Isolation: When multiple agents work concurrently, design state files to avoid race conditions. Simple approach: each agent uses its own progress file, or use git branches for isolation. Concurrent writes to the same file are a common source of trouble.
  • Durability: Critical project knowledge lives in git-tracked files. Temporary state can stay in session memory, but knowledge that must survive across sessions has to be written to files. What's in your head doesn't count, only what's written down counts.

Trace It: The 30-Microservice Repo

A team's e-commerce platform has ~30 microservices. Architecture decisions, inter-service protocols, data consistency strategies, API versioning rules, live in Confluence (partially outdated), Slack (hard to search), a few senior engineers' heads, and sporadic code comments.

Predict before reading on: an agent gets assigned a task in this repo. What happens?

Trace it against the fresh-session test from earlier: the agent can only act on what's written down. Every implicit constraint that "everyone knows but nobody wrote" is invisible to it, it has no way to know what it doesn't know, so it steps into the trap the same way a new hire would, except it can't ask a hallway question to catch itself first.

The fix follows straight from durability: put the missing knowledge in git.

  1. AGENTS.md at repo root, overview, stack versions, global hard constraints
  2. ARCHITECTURE.md in each microservice directory, that service's responsibilities, interfaces, dependencies
  3. Centralized CONSTRAINTS.md, explicit "MUST / MUST NOT" language
  4. PROGRESS.md per service, current work status

Faded case

Skip to the open case if this is familiar. A different team's payments-service, the one from this lecture's opening, has grown a dozen services around it: fraud-scoring, refunds, ledger-sync, notifications. Its AGENTS.md covers the root overview and hard constraints well. ARCHITECTURE.md exists in six of the twelve service directories; the other six have nothing. PROGRESS.md exists nowhere. An agent picks up a task in ledger-sync, one of the six without an ARCHITECTURE.md.

Before reading on, decide: run the fresh-session test against this setup. Which of the five questions does the agent fail on ledger-sync, and which map-drawing principle is the fix?

Open case

Pick one service, module, or package in your own repository, the one you'd least want to hand an agent cold, with the least documentation and the most tribal knowledge behind it. Run the fresh-session test against it: five questions, repo contents only, no verbal context, no hints from you. Note which questions it fails and which artifact from this lesson's four principles would close each gap. Then check whether that gap is global, and belongs in your root entry file, or local to this one module, and belongs next to it, before you write a single line.

Key Takeaways

  • Knowledge not in the repo doesn't exist for the agent. Putting critical decision information into the repository is the most fundamental harness investment, draw a good map so you don't get lost.
  • Use the "fresh session test" to evaluate repo quality: can a brand-new session answer five basic questions using only repo contents?
  • Knowledge should be near code, minimal but complete, and updated together with code. It's not about writing more docs, it's about putting information in the right place.
  • Use ACID principles for agent state: atomic commits, consistency verification, concurrency isolation, and durable critical knowledge.
  • Knowledge decay is the biggest enemy. Out-of-date documentation is more dangerous than no documentation at all, it sends the agent in the wrong direction while the agent thinks it's on the right track.

Example Files

Copy-ready course examples referenced in this lecture.

repo-knowledge-layout.txt

A reference directory layout for a repo that serves as system of record, entry file at root, architecture/product/reliability docs plus per-topic references under docs/, and plans split into active vs completed.

text
AGENTS.md
docs/
  ARCHITECTURE.md
  PRODUCT.md
  RELIABILITY.md
  references/
    electron.md
    sqlite.md
  plans/
    active/
    completed/
src/
scripts/

repo-reader.ts

A runnable discoverability scorer: point it at any repo and it awards points for the artifacts a fresh agent session needs (entry file, docs dir, architecture docs, feature tracking, handoff files, tests, config, README) and lists exactly what's missing.

ts
/**
 * repo-reader.ts
 *
 * Reads a directory structure and scores it on discoverability.
 * Checks for: AGENTS.md, docs/, architecture docs, feature tracking,
 * handoff files, and other signals of a repository that serves as the
 * system of record.
 *
 * Usage:
 *   npx tsx docs/lectures/lecture-03.../code/repo-reader.ts [path]
 *   (defaults to current working directory if no path given)
 *
 * Run: npx tsx docs/lectures/lecture-03-why-the-repository-must-become-the-system-of-record/code/repo-reader.ts
 */

import * as fs from "node:fs";
import * as path from "node:path";

// ---------------------------------------------------------------------------
// Scoring criteria
// ---------------------------------------------------------------------------

interface Check {
  name: string;
  description: string;
  maxPoints: number;
  check: (dir: string) => { points: number; found: string[]; missing: string[] };
}

const checks: Check[] = [
  {
    name: "AGENTS.md / CLAUDE.md",
    description: "Agent-readable instruction file at repo root",
    maxPoints: 15,
    check: (dir) => {
      const candidates = ["AGENTS.md", "CLAUDE.md", ".claude/CLAUDE.md"];
      const found = candidates.filter((f) => fs.existsSync(path.join(dir, f)));
      return { points: found.length > 0 ? 15 : 0, found, missing: found.length > 0 ? [] : candidates };
    },
  },
  {
    name: "Documentation directory",
    description: "Dedicated docs/ or documentation/ directory",
    maxPoints: 10,
    check: (dir) => {
      const candidates = ["docs", "documentation", "doc"];
      const found = candidates.filter((f) => {
        const p = path.join(dir, f);
        return fs.existsSync(p) && fs.statSync(p).isDirectory();
      });
      return { points: found.length > 0 ? 10 : 0, found, missing: found.length > 0 ? [] : ["docs/"] };
    },
  },
  {
    name: "Architecture documentation",
    description: "Files describing system architecture",
    maxPoints: 15,
    check: (dir) => {
      const patterns = [
        "architecture.md", "ARCHITECTURE.md", "docs/architecture.md",
        "docs/architecture/", "design.md", "DESIGN.md",
      ];
      const found = patterns.filter((f) => fs.existsSync(path.join(dir, f)));
      return { points: found.length > 0 ? 15 : 0, found, missing: found.length > 0 ? [] : ["architecture.md or docs/architecture/"] };
    },
  },
  {
    name: "Feature tracking",
    description: "Feature list or task tracking file",
    maxPoints: 15,
    check: (dir) => {
      const patterns = [
        "feature_list.json", "features.md", "FEATURES.md",
        "docs/features.md", "tasks.json", "TODO.md",
      ];
      const found = patterns.filter((f) => fs.existsSync(path.join(dir, f)));
      return { points: found.length > 0 ? 15 : 0, found, missing: found.length > 0 ? [] : ["feature_list.json or features.md"] };
    },
  },
  {
    name: "Handoff / session continuity",
    description: "Files for multi-session continuity",
    maxPoints: 15,
    check: (dir) => {
      const patterns = [
        "HANDOFF.md", "handoff.md", "SESSION_NOTES.md",
        "docs/handoff.md", ".handoff", "PROGRESS.md",
      ];
      const found = patterns.filter((f) => fs.existsSync(path.join(dir, f)));
      return { points: found.length > 0 ? 15 : 0, found, missing: found.length > 0 ? [] : ["HANDOFF.md or PROGRESS.md"] };
    },
  },
  {
    name: "Testing structure",
    description: "Test directory or test configuration",
    maxPoints: 10,
    check: (dir) => {
      const patterns = ["test", "tests", "__tests__", "spec"];
      const found = patterns.filter((f) => {
        const p = path.join(dir, f);
        return fs.existsSync(p) && fs.statSync(p).isDirectory();
      });
      return { points: found.length > 0 ? 10 : 0, found, missing: found.length > 0 ? [] : ["test/ or tests/"] };
    },
  },
  {
    name: "Configuration files",
    description: "Project config (package.json, tsconfig, etc.)",
    maxPoints: 10,
    check: (dir) => {
      const patterns = ["package.json", "tsconfig.json", "pyproject.toml", "Cargo.toml", "go.mod"];
      const found = patterns.filter((f) => fs.existsSync(path.join(dir, f)));
      return { points: found.length > 0 ? 10 : 0, found, missing: found.length > 0 ? [] : ["package.json or equivalent"] };
    },
  },
  {
    name: "README",
    description: "Root README file",
    maxPoints: 10,
    check: (dir) => {
// … trimmed for the lecture — the pattern continues in the same shape

system-of-record-checklist.md

The fresh-session test as a seven-question checklist, run it against your own repo before and after drawing the map.

markdown
# System of Record Checklist

Can a fresh agent discover the following from the repo alone?

- What product is being built?
- What the app should do for users?
- How the codebase is organized?
- How the app starts?
- How health is checked?
- What work is currently in progress?
- What quality standards matter?

What You Have Now

A repository map the agent can load: what exists, where it lives, what is authoritative.

Write it as a file the agent will actually read, not a diagram for humans. Every later lecture assumes the agent can answer "where does X live?" from this map instead of guessing.

Save it as harness/repo-map.md; the lab's checker looks for that file at that path.

Further Reading

Exercises

  1. Fresh session test: Open a completely fresh agent session in your project (provide no verbal context whatsoever), let it see only the repository contents, then ask it five questions: What is this system? How is it organized? How do I run it? How do I verify it? What's the current progress? Record which ones it can't answer, then improve the repo until it can answer all of them.

  2. Knowledge externalization quantification: List all decisions and constraints important to development work in your project. Mark each item as inside or outside the repo. Calculate your knowledge visibility gap (the proportion of items outside the repo). Make a plan to shrink that gap to as close to zero as you can get.

  3. ACID assessment: Evaluate your project's state management using this lecture's ACID analogy. Atomicity, can agent operations be cleanly rolled back? Consistency, does the repo have "consistent state" verification? Isolation, do multiple concurrent agents step on each other's toes? Durability, is all cross-session knowledge properly persisted?

Check your understanding


Reading is free — your progress isn't being saved

Nothing you did on this page is recorded. Paid students get saved progress and verified completions, recorded quiz answers, the spaced-repetition review queue, labs, and a certificate for each course they finish.

30-day money-back guarantee. One-time payment — lifetime access and updates.