Here is a session that happens to everyone about a week into working with a coding agent.
You ask for something reasonable ("add team invites") and forty minutes later you have a diff touching nineteen files. Some of it is good. Some of it solves a problem you do not have. There is a new dependency you did not agree to and a database column you cannot explain. Reviewing it costs more than writing it would have. So you throw it away, ask again more carefully, and get a different nineteen files.
The reflex is to blame the model. The actual problem is structural: the request never became a written artefact, so there was no point at which anyone could disagree cheaply. Every disagreement had to be expressed as a rewrite.
Compound Engineering is the fix, and it is not complicated: make the thinking a file, execute against the file, then write down what you learned. The compounding is the third step, which is the one everybody drops.
The wrong way: conversation as the only artefact
you: add team invites
agent: [starts editing src/, invents a schema, picks an email template,
decides invites expire in 24 hours]
you: no, seven days, and only owners can invite
agent: [rewrites]
you: also we already have a workspace_members table
agent: [rewrites again]
Three things are wrong here, and none is about model quality.
The decisions (expiry, permissions, existing schema) surfaced as code, which is the most expensive form. Nothing survives the session: tomorrow the same questions get answered differently, because the answers live in a chat log nobody will reopen. And there is no verification standard, because "add team invites" cannot be checked. Done is whenever both parties get tired.
The right way: four artefacts, in order
1. A spec, in docs/plans/. Run /write-spec. It reads the code first,
asks the five questions only a human can answer, and writes a file:
---
title: Team invites for workspace owners
status: draft
---
## Problem
Owners can only add members who already have an account...
## Scope
In: email invite, 7-day link, seat check, revoke.
Out: bulk CSV import, SSO provisioning, invite reminders.
## Behaviour
Given an owner on a workspace with 3 of 5 seats used
When they invite a new member by email
Then an invite row is created with status "pending"
And the seat count shows 4 of 5 immediately
The Out list is the most valuable part. It is a decision, recorded, that stops
the change doubling in week two.
A human reads this and sets status: approved. That pause is the whole
mechanism, and in team mode the plan-gate hook makes it structural: edits under
src/ are refused until an approved plan exists.
2. An ordered plan: /ce-plan. It takes the approved spec and turns it into
steps with files attached: which migration first, which handler next, which test
proves each one. It resolves the sequencing questions ("migration before the code
that reads it") while they are still free to change.
3. Execution: /ce-work. It implements the plan, in order, and stops when
the plan is done rather than when it runs out of ideas. Because the plan names
files and acceptance criteria, "done" is checkable by someone who was not in the
conversation. The guard hooks run underneath: auto-lint on each edit,
enforce-typecheck if it reaches for a bare tsc, env-leak-detector if a
credential appears.
4. Verification. /qa-feature walks the acceptance criteria, breaks the
feature deliberately, and reports pass / fail / not tested. Then pr-reviewer
reviews the diff against this repo's rules, not against generic taste.
The step everyone skips
/ce-compound, or the documentarian agent, writes what was learned into
docs/solutions/. One file, one problem, frontmatter so it is findable:
---
title: Invite links break when the app URL has a trailing slash
summary: NEXT_PUBLIC_APP_URL is concatenated, not joined, so a trailing slash produces a double-slash path that the middleware matcher misses.
tags: [nextjs, env, middleware, invites]
---
Skipping this is why the loop stops compounding. Without it you have a nice
process that costs you a planning step and returns nothing. With it, the next
person who hits that problem finds the answer in twenty seconds, and "the next
person" is usually you, or an agent reading docs/solutions/ at the start of a
session.
When the same correction happens twice, escalate it from a doc to a rule. Ask
the system-manager agent to write a path-scoped rule, and the mistake stops
being available rather than being caught again.
What this actually costs
Ten to twenty minutes of planning per unit of work. It buys back the review cost of a diff nobody understands, the rework from decisions surfacing as code, and the third time somebody solves the same problem.
The exemption is real work: a typo, a copy change, a one-line fix with an obvious verification. Planning a two-line change is bureaucracy, and bureaucracy is how a good process gets abandoned. The test is whether a second engineer could implement it and produce roughly the same thing. If yes, skip the plan.
The loop, end to end
request
-> /write-spec docs/plans/<date>-<slug>.md, status: draft
-> human approval status: approved (plan-gate opens)
-> /ce-plan ordered steps, files named
-> /ce-work implementation
-> /qa-feature evidence, not "it works"
-> pr-reviewer against this repo's rules
-> /deploy-to-vercel preview, promote, watch
-> /ce-compound docs/solutions/, and a rule if it repeats
Seven steps, and the last one is the only one that makes the next pass shorter. A team that runs the first six has a tidy process. A team that runs all seven has a repo that gets easier to work in every month, which is the entire point of the word "compound".