# BACKPRESSURE.md
A file format for defining deterministic self-verification checks that AI coding agents run on their own output. Like `AGENTS.md` tells agents how to behave, `BACKPRESSURE.md` tells agents how to know they are wrong.
## The Problem
Agents carry assumptions. Some come from docs. Some come from model weights. Some come from your prompts. When an assumption is wrong, it leaks through research into planning into implementation. You find out 2,000 lines deep that something fundamental was incorrect.
The fix is not more planning. The fix is giving agents a way to check their own work without asking you. Compilers, type checkers, test suites, linters, eval harnesses. These are deterministic. They return pass or fail. No opinions. No LLM-as-judge. Binary.
`BACKPRESSURE.md` is a structured file that enumerates every deterministic check an agent should run to verify its work. It is the harness design, separated from the implementation.
## Why a Separate File
- `AGENTS.md` / `CLAUDE.md` describe how agents should work in this repo
- `SKILL.md` teaches agents a specific capability
- `BACKPRESSURE.md` defines how agents verify correctness
These are different concerns. Mixing verification checks into agent instructions buries them. A dedicated file makes the contract explicit: here is every way we will know the code is correct, listed in one place.
## The Format
`BACKPRESSURE.md` is a Markdown file placed at the root of your project (or in subdirectories for monorepos). It contains ordered sections of checks, each with a command, expected result, and run conditions.
### Minimal Example
```markdown
# BACKPRESSURE.md
## Build
- `npm run build` — must exit 0, zero errors
## Types
- `npx tsc --noEmit` — must exit 0, zero type errors
## Tests
- `npm test` — all tests pass, no regressions
## Lint
- `npm run lint` — zero errors (warnings acceptable)
```
### Full Format
```markdown
# BACKPRESSURE.md
> Deterministic verification checks for [project-name].
> Agents: run these checks after every code change. Do not proceed if blocking checks fail.
## Build
<!-- Checks that the project compiles/builds successfully -->
- `command` — expected result
- severity: blocking | warning
- when: after-every-change | before-commit | on-demand
## Types
<!-- Static type checking -->
## Tests
<!-- Unit, integration, e2e test suites -->
## Lint
<!-- Code style and formatting -->
## Architecture
<!-- Dependency boundaries, import rules, structural constraints -->
## Contracts
<!-- Learning tests: assertions about external system behavior -->
## Performance
<!-- Latency, memory, bundle size budgets -->
## Custom
<!-- Project-specific checks that don't fit above categories -->
```
### Check Format
Each check follows this structure:
```markdown
- `<command>` — <expected result>
- severity: blocking | warning
- when: after-every-change | before-commit | on-demand
- notes: <optional context for why this check exists>
```
**Fields:**
| Field | Required | Values | Description |
|-------|----------|--------|-------------|
| command | yes | shell command | What to run |
| expected result | yes | plain text | What "pass" looks like |
| severity | no (default: blocking) | `blocking` or `warning` | Blocking checks must pass before proceeding. Warnings are informational. |
| when | no (default: after-every-change) | `after-every-change`, `before-commit`, `on-demand` | How frequently the check should run |
| notes | no | plain text | Context: why this check exists, what broke without it |
### Sections
Use the sections that apply to your project. Skip what does not apply. The order is intentional: build first (fast, catches compilation errors), types second (catches structural errors), tests third (catches behavioral errors), then everything else.
| Section | Purpose | Examples |
|---------|---------|----------|
| Build | Does it compile? | `cargo build`, `npm run build`, `go build ./...` |
| Types | Are the types correct? | `npx tsc --noEmit`, `mypy src/`, `pyright` |
| Tests | Does behavior match expectations? | `pytest`, `npm test`, `cargo test` |
| Lint | Is the code clean? | `eslint .`, `ruff check .`, `clippy` |
| Architecture | Are structural constraints preserved? | Import restrictions, dependency boundaries, module isolation |
| Contracts | Do external systems behave as assumed? | Learning tests against APIs, SDKs, CLIs you do not control |
| Performance | Are budgets maintained? | Latency thresholds, bundle size limits, memory caps |
| Custom | Project-specific | Eval harness accuracy, migration integrity, schema validation |
## The Workflow
### 1. Human Writes BACKPRESSURE.md (or Agent Generates It)
Before implementation begins, define the checks. You can write this by hand, or use the included `AGENTS.md` / `SKILL.md` to have an agent generate it from your PRD or codebase.
```
Input: PRD, existing codebase, or both
Output: BACKPRESSURE.md with project-specific checks
```
### 2. Agent Reads BACKPRESSURE.md During Implementation
The agent treats this file as its verification contract. After every code change, it runs the relevant checks. If a blocking check fails, it fixes the issue before proceeding. No human required.
```
Write code → Run checks → Fix failures → Run checks again → Proceed
```
### 3. Human Reviews Design, Not Correctness
When the agent finishes, the human reviews for design quality and intent. Functional correctness was already verified by the checks. This is the leverage: the human spends time on what only a human can evaluate.
### 4. BACKPRESSURE.md Evolves
When something breaks that the checks did not catch, add a new check. The file is append-friendly. Over time, it becomes a comprehensive contract between you and the agent about what "correct" means for this project.
## Agent Integration
### Claude Code / CLAUDE.md
Add to your `CLAUDE.md`:
```markdown
## Verification
Read `BACKPRESSURE.md` before starting implementation. After every code change:
1. Run all `after-every-change` checks
2. If any blocking check fails, fix the issue before proceeding
3. Before committing, run all `before-commit` checks
4. Log which checks passed/failed in your task summary
```
### Cursor / .cursorrules
Add to your `.cursorrules`:
```
When implementing features:
1. Read BACKPRESSURE.md for verification checks
2. Run blocking checks after every code change
3. Do not proceed past a failing blocking check
4. Before marking a task complete, run all checks
```
### Codex / AGENTS.md
Add to your `AGENTS.md`:
```markdown
## Back Pressure
This project uses BACKPRESSURE.md for deterministic self-verification.
Run all blocking checks after code changes. Do not proceed on failure.
```
## Generating BACKPRESSURE.md
This repo includes two tools for generating `BACKPRESSURE.md` from an existing project:
1. **`AGENTS.md`** — Instructions for Claude Code to analyze a codebase and generate `BACKPRESSURE.md`
2. **`SKILL.md`** — A Cursor Agent Skill that does the same via the skill invocation pattern
### Quick Start
**With Claude Code:**
```
Read AGENTS.md in the backpressure repo, then analyze my project at /path/to/project and generate a BACKPRESSURE.md for it.
```
**With Cursor:**
Install the skill, then invoke: "Generate a BACKPRESSURE.md for this project."
## Examples
See the `examples/` directory:
- [`fastapi-app.md`](examples/fastapi-app.md) — Python FastAPI backend with database
- [`nextjs-app.md`](examples/nextjs-app.md) — Next.js frontend with TypeScript
- [`python-cli.md`](examples/python-cli.md) — Python CLI tool with packaging
## Key Principles
1. **Deterministic over probabilistic.** Every check should return the same result given the same input. No LLM-as-judge. If the check has opinions, it is not a check.
2. **Blocking checks block.** If a check is marked blocking, the agent must stop and fix before continuing. This is the entire point. Soft enforcement is not enforcement.
3. **Start with what you have.** If your project has a test suite, that is a check. If it has a linter, that is a check. If it has a type checker, that is a check. `BACKPRESSURE.md` is not asking you to build new infrastructure. It is asking you to list the infrastructure you already have in one place where the agent can find it.
4. **Add checks when things break.** Every time an agent produces incorrect output that the existing checks did not catch, add a check that would have caught it. The file grows through production incidents, not upfront design.
5. **Contracts section is for learning tests.** When you depend on external systems you cannot read the source of (APIs, SDKs, CLIs), write small assertion-based tests that verify your assumptions about their behavior. List those tests in the Contracts section. When you upgrade a dependency, rerun them.
## Attribution
The concept of "back pressure for AI coding agents" comes from the [AI That Works](https://www.youtube.com/@AIThatWorks) podcast by Dexter (Boundary) and Vibb (Human Lair). The term "learning tests" was coined by Michael Feathers in *Working Effectively with Legacy Code*.
This repo formalizes the pattern into a file format and agent workflow.
## License
MIT