Who does what
Our method has a short version on How we build: agents write the code, an engineer owns every change. The engineer writes the spec, plans each change and reviews every diff. The agent does the typing. The engineer decides what merges.
The repo behind farcholabs.com works this way. From September 26 to October 12, 2026, 108 pull requests were merged into it: the site, the admin and CRM, the API and its worker. Each one went through the same path.
Interactive figure
The path every change takes
- Checks in CI
- 13: 8 web, 5 API
- Last run (example)
- all 13 green
web · 8
- API types drift: passed
- typecheck: passed
- lint: passed
- contrast: passed
- SEO: passed
- i18n: passed
- articles: passed
- build: passed
API · 5
- ruff: passed
- ruff format: passed
- mypy: passed
- pytest on a MongoDB replica set: passed
- openapi.json drift: passed
Every change in this repo takes this path. Send one through, or break something on purpose.
Example runs, sped up. Repo facts as measured for the post on Oct 16, 2026 (commit 8e758ff).
An agent is fast and has no memory of yesterday. Every session starts from what the repo says. So the repo has to say three things: how the project works, what was already decided, and when a change is wrong.
Notes the agent reads first
At the root sits CLAUDE.md, 155 lines long. Agents read it at the start of every session. It holds the layout of the repo, the commands to run each app and its checks, and the rules that don't show in the code: who may call the API, where money is stored and how, what never goes on the site.
Each app adds its own. apps/web/AGENTS.md has 126 lines on the web app alone: where a new page must be listed, how caching works, which components the admin is built from. It also carries a block that Next.js writes itself, warning the agent that this version of the framework differs from what it may remember and pointing it to the docs installed with the package.
## Rules
- **Contract:** a change to API routes or models regenerates `apps/api/openapi.json` and
`apps/web/lib/api/schema.d.ts` in the same commit. Both workflows fail on drift.
- **Owner decisions in content:** copy that depends on an open D item (prices, legal name,
contact, the founder) reads it from `apps/web/lib/launch.ts` and leaves the detail out
while it is open; never write a guess into a page.
- **Before committing,** run the checks of every app you touched (commands above).
All must pass.Good rules here are concrete. "Keep the API and the frontend in sync" is advice. "Regenerate these two files in the same commit, CI fails on drift" is a rule an agent can follow and a check can enforce.
Decisions on paper, and the ones an agent can't take
The repo has eight architecture decision records in docs/adr: the platform, sign-in for the admin, hosting, the domain, leaving Cloudflare, the blog and the site's chat. Each says what was chosen, what was weighed and what follows from it. When an agent wonders why the worker is a Cloud Run job, the answer is a file, not a guess.
Some questions only the owner can answer: the legal name, the prices, how clients pay. docs/PLAN.md lists them as D1 to D19, and CLAUDE.md says it plainly: the owner decides the D items, never settle one silently in code. While one is open, a page that depends on it leaves the detail out.
The answers live in one file, apps/web/lib/launch.ts. An open one is null, and a short script lists them and fails while any is left:
// apps/web/scripts/check-launch.mjs
const { openDecisions } = await import("../lib/launch.ts");
const pending = openDecisions();
if (pending.length === 0) {
console.log("Every owner decision the site needs is answered.");
} else {
console.error(`Not ready to publish: ${pending.length} owner decision(s) open (answer them in lib/launch.ts).`);
for (const decision of pending) console.error(` ${decision.id} (${decision.key}): ${decision.question}`);
process.exitCode = 1;
}Why this matters
An agent asked to finish a pricing page will write a price if nothing stops it. A null in one file, and a rule that says to leave the detail out, turns a guess into a visible gap the owner fills.
Checks that say no
Review catches what a person sees. Checks catch the rest, on every pull request, before anyone looks. Our CI runs 13 of them, split across two workflows that each run only when their app changes:
- On the web, 8: the API types match the API's OpenAPI file, the type check, lint, WCAG AA contrast for every color token in both themes, every title and description within search limits, the three languages in step, the guides' figures safe and described, and the build.
- On the API, 5: lint, formatting, the type check, the tests against a real MongoDB, and the OpenAPI file matching the code.

Each check is a mistake that can no longer reach production: a title past 60 characters, a Spanish page missing a key the English one has, a diagram with a fixed color that disappears in dark mode. A reviewer doesn't have to remember them; a script does. CI only validates. It deploys nothing; the owner does.
- lines in the root CLAUDE.md
- 155
- architecture decision records
- 8
- checks in CI on every pull request
- 13
This post took the same path
A scheduled task drafted this post. It took the next topic the founder approved in a list kept in the repo, read the rules for posts and the files the topic cites, wrote it in English and Spanish, and saved it as a draft. The API checked it before saving: the words, the visuals, both languages, a safe diagram. It can't publish.
Then the founder reads it, changes what needs changing and publishes it from the admin. Publishing is the founder's signature, the same way a merge is.
The agent does the typing. The engineer decides what merges.
What to copy into your repo
- 01An agent notes file at the root, with the layout, the commands and the rules the code doesn't show. Concrete enough that a script could check each rule.
- 02One short decision record per architectural choice, with the options you turned down.
- 03A list of the questions only the owner answers, and a rule that a page leaves the detail out until they do.
- 04A check for every mistake you don't want a reviewer to have to remember, run on every pull request.
- 05A person who reads every diff and is the only one who can merge.
Every repo we hand over to a client comes with these files. How we build has the whole method, and if you have a product in mind, send us a brief. A person reads it.


