· 7 min read ·

Context Anchoring and the Feedback Loop That Decision Documentation Never Had

Source: martinfowler

Every software team has documentation that lies. The wiki that describes the architecture from two refactors ago. The README that still references the old deployment pipeline. The ADR that records a decision that was quietly reversed six months later. This drift is so normal that most developers have stopped treating internal docs as authoritative. They read the code instead.

AI-assisted development is changing the stakes of that tradeoff. When a coding assistant like Claude Code or Cursor starts a session, it begins with no memory of your project, your decisions, your conventions, or the reasoning behind any of them. Each session is a blank slate. Rahul Garg’s Context Anchoring piece on Martin Fowler’s site names and formalizes the response to this problem: externalize decision context into a persistent, living document that gets injected into every AI session from the start.

The mechanism is straightforward. Claude Code reads a CLAUDE.md file at the project root. Cursor reads .cursorrules. GitHub Copilot reads .github/copilot-instructions.md. Aider reads CONVENTIONS.md. Each tool has its own file convention, but the idea is the same: a structured document that establishes project context before the first message is typed.

What Goes in an Anchor Document

An anchor document is not a README. READMEs are written for humans onboarding to a project; they explain what it does and how to run it. An anchor document is written for an AI collaborator operating on the project right now; it establishes constraints, patterns, and hard boundaries.

A minimal but effective anchor document covers:

# Project: OrdersService

## Stack
- Language: Go 1.23
- Database: PostgreSQL 16 via pgx (no ORM)
- Message broker: NATS JetStream
- Deployment: Kubernetes, Helm charts in /deploy

## Architecture
- Hexagonal: domain logic in /internal/domain, infrastructure adapters in /internal/infra
- No business logic in HTTP handlers or repository implementations
- All errors are typed — no raw string errors, no panic outside main

## Conventions
- Table-driven tests, no testify — use standard library testing package
- Structured logging via slog, JSON format, no fmt.Printf
- Context propagation: every function that touches I/O takes ctx as first argument

## Hard Constraints
- Do not modify /internal/domain/events.go — it is shared with the events team
- Migration files are append-only — never modify an existing migration
- No new external dependencies without updating go.mod and noting the reason here

## Key Decisions
- Using pgx directly (not GORM) because the team needs custom COPY operations for bulk import. See ADR-0004.
- NATS over Kafka because operational complexity at our scale does not justify Kafka. See ADR-0011.

This is a different kind of document from an ADR, though the two are related. ADRs, formalized by Michael Nygard and refined through years of practice at Thoughtworks and elsewhere, capture a single decision with its full context and rationale. They are narrative artifacts written for future humans who need to understand why things are the way they are. An anchor document is a distillation: it collapses the currently-active ADRs into operational instructions written for an AI agent that needs to know what to do right now, not why it was decided years ago. The anchor document typically references ADRs for anyone who wants the full story.

The Forcing Function

Here is where context anchoring diverges from previous documentation practices in a way that matters. Writing a decision down for an AI requires precision that human teams routinely avoid.

Consider the difference between these two phrasings of the same decision:

  • Human-readable ADR version: “We chose to use a repository pattern to decouple business logic from persistence concerns.”
  • Anchor document version: “No direct database calls in service layer. All persistence goes through repository interfaces in /internal/domain/ports. Service code must not import anything from /internal/infra.”

The first version is accurate but vague. A human developer reading it understands the intent and applies judgment. An AI assistant given only the first version will sometimes produce direct database calls in service methods, because the model cannot infer the import boundary from the principle alone. The second version is precise enough to be actionable.

This precision requirement is a forcing function for team clarity. Many architectural decisions exist as shared intuitions: everyone on the team “knows” not to do X, but nobody has written it down because the knowledge feels obvious. When you start writing anchor documents, those implicit constraints must become explicit. The exercise of writing the anchor document often reveals that the team holds different versions of the same intuition.

Cyrille Martraire’s work on living documentation is a useful predecessor here. Martraire argues that documentation should be derived from or synchronized with code, making staleness structurally impossible rather than something you fight through discipline. Context anchoring takes a different path to a similar destination: rather than generating docs from code, it makes inaccurate docs immediately visible through AI behavior.

The Feedback Loop

This is the genuinely novel property of anchor documents compared to all previous documentation practices. If your anchor document is wrong, the AI makes wrong suggestions, and developers notice in real time.

Every other documentation artifact has a weak feedback loop. A stale ADR sits in docs/decisions/ and nobody reads it until a new developer asks a question. A misleading README produces confusion during onboarding, which happens infrequently. The lag between documentation becoming wrong and someone discovering it is measured in weeks or months.

With an anchor document, the lag is minutes. If your document says “no direct SQL queries” but the pattern has evolved to allow raw queries for reporting endpoints, the AI will resist writing the reporting query or will write it in a way inconsistent with how your team has actually been doing it. Developers notice immediately. The anchor document is edited. The system self-corrects.

This feedback loop also makes anchor documents more honest than ADRs about the current state of a codebase. ADRs capture what was decided; anchor documents must capture what is currently true, or the AI becomes a constant source of friction. A team that treats its anchor document with the same discipline as production code has, as a side effect, a reasonably accurate record of how the codebase actually operates today.

Session-Level vs. Project-Level Anchoring

Not everything in a context document is stable across all sessions. Some constraints are project-wide and permanent. Others apply only to the current task.

A practical pattern is to split the anchor document into stable sections (architecture, conventions, hard constraints) and a mutable “current session” section that gets updated at the start of each significant work session:

## Current Session Context
- Working on: payment webhook handler for Stripe events
- Relevant files: /internal/infra/http/webhooks.go, /internal/domain/payments/
- Do not touch: /internal/domain/events.go (being modified in branch feature/event-schema-v2)
- Approach: process events idempotently using event ID as deduplication key in payments table
- Open question: clarify with team whether refund events should trigger the same notification flow as charges

This session section is ephemeral by design. It captures the short-term state that the AI needs for this work without polluting the permanent project record with task-level details.

Across Tools

Each major AI coding tool has settled on a slightly different convention. Claude Code’s CLAUDE.md supports a hierarchical structure: a root-level file for project-wide context, plus subdirectory-level CLAUDE.md files for module-specific constraints. This is particularly useful in monorepos where different services have different conventions. Cursor’s newer Rules for AI system goes further, allowing rules to be scoped to specific file patterns, so you can have different instructions apply when editing test files versus source files.

GitHub Copilot’s .github/copilot-instructions.md is a newer addition and currently less granular than the Claude or Cursor equivalents, but its placement in .github/ makes its purpose legible to any developer examining the repository: this is a configuration file for AI tooling, sitting alongside CI configuration and other automation.

The fragmentation is an annoyance for teams using multiple tools. Writing and maintaining separate files for Claude, Cursor, and Copilot with overlapping but not identical content adds overhead. Some teams maintain a single authoritative source and generate tool-specific files from it; others accept the redundancy as the cost of using multiple tools.

What This Practice Is Really About

Context anchoring solves a surface problem (AI sessions are stateless) by addressing a deeper one (teams have never had a good mechanism for maintaining a concise, accurate, operational record of how a codebase actually works right now). ADRs give you the history. READMEs give you the overview. Neither gives you the precise, current, AI-legible constraints that an anchor document provides.

The pattern is early in its formalization. The Martin Fowler article is one of the first pieces to give it a name and treat it as a distinct practice rather than an informal habit. The tooling conventions are still settling. But the underlying problem, that software teams externalize too little of their decision context and pay for it constantly, is not new. AI-assisted development is just making the cost of that underexternalization more immediate and visible.

Was this interesting?