Before You Let the Agent Build It
The first question is still whether the work should exist.
Published
A detailed plan can make a bad idea look very organised.
The agent has broken the work into stages. It has identified files, proposed tests, explained the dependencies, and written a confident account of how everything fits together. You can read it and feel that the thinking has been done.
The first question is still whether the work should exist.
I don’t mean whether the feature sounds useful in isolation. Almost anything can be made to sound useful. I mean whether this is the right change, in the right place, for the problem we actually have. Whether there is already something that owns the responsibility. Whether the plan is fixing the cause or giving us another place to manage its consequences.
That is the reason I care about planning and adversarial review. I want the best code I can get from the model. Following a plan is only useful after the plan has earned the right to be followed.
Read what is already there
An agent can produce a convincing architecture before it has understood the existing one. So can a human. The explanation is often perfectly coherent on its own. The problem appears when it meets the system it was meant to improve.
Before designing a new piece, inspect the current code, the call paths, the contracts, and the relevant plans. Write down who owns the responsibility today. Where does the state live? Who changes it? Which consumers rely on it? What happens when the process restarts or an external operation completes?
Those questions are concrete enough to disagree about. “We need a more flexible layer” is much harder to evaluate because it can mean almost anything.
Take a hypothetical cache. Adding one might make an individual call faster. It also introduces decisions about freshness, invalidation, scope, and recovery. If an existing component already owns those decisions, a second cache may create a problem larger than the one it solves. If the new responsibility really is distinct, the plan should explain why.
A small diagram of actual ownership can be worth more than ten pages describing a new abstraction.
Here is how that cache proposal should earn its place. Suppose the complaint is that a permissions lookup is slow. The agent proposes a cache inside the HTTP adapter. It has a tidy interface, a time-to-live, and tests showing a faster second request.
The reviewer follows the call and finds that the permissions service already caches decisions and invalidates them when access changes. The slow adapter is bypassing that service. The proposed cache would create a second answer to the question “may this person do this?”
The right plan now has less architecture in it: route the adapter through the existing owner, then exercise the request before and after a permission is revoked. A benchmark of two warm calls would have passed the original plan. It would never have shown that revoked access could survive in the new cache.
This is a hypothetical example, but it is the kind of disagreement I want. The reviewer has questioned the plan’s right to exist and named the behaviour that settles the argument.
Keep the plan readable by the person responsible
A plan is a place to make decisions visible. It should explain the intended behaviour, the part of the system that owns it, the change being proposed, and the evidence that would establish the result.
It does not need to sound like a legal document. If I have to decode a new vocabulary before I can disagree with the work, the plan is getting in the way.
The same applies to acceptance criteria. “All checks pass” tells me very little until I know which behaviour those checks exercise. “A second tenant cannot read the first tenant’s state” is a claim about a real boundary. The test has to reach that boundary, under the conditions the requirement describes.
A plan can also say what would make it unnecessary. Perhaps the capability is already present. Perhaps a smaller correction solves the problem. Perhaps the cost is not justified by the use case. That is useful engineering information, even when it ends with less code to write.
Give the reviewer permission to reject the premise
Review often starts too late. By the time someone is examining the implementation, the proposed feature has acquired momentum. There is a branch, a diff, a test suite, and a lot of work everyone would prefer not to throw away.
Challenge the premise while it is still cheap to change.
What existing responsibility does the plan duplicate? Which assumption has not been checked? Is a new lifecycle necessary? Are we changing a shared interface as though only one consumer exists? Does the demonstration actually prove the requirement?
The reviewer needs to explain the objection, not just announce that the plan feels overengineered. A useful challenge can be answered. Show the unserved consumer, the distinct state boundary, the measured constraint, or the behaviour the current owner cannot support.
Adversarial review is not a competition to find reasons to say no. It is a way to make the proposal defend its place in the system. Sometimes the new abstraction is justified. Sometimes the best change is to remove an old one. The evidence should determine that, rather than a preference for either more features or smaller diffs.
Agreement is not the same as independent evidence
Several agents agreeing can feel reassuring. It helps to ask what they are agreeing from.
They may share the same incomplete description, the same assumptions, or closely related model behaviour. If the important source was absent from every context, several confident reviews do not make it appear.
A reviewer should inspect the actual requirement and change. Where independent models are used, be precise about what that independence means. A separate model can reduce some correlated blind spots. It does not automatically create an independent organisation, a separate operator, or a trustworthy account of external state.
The work still needs evidence at the boundary that matters. A local test proves what it exercised. A provider readback establishes something different from a prepared request. A restart check answers a question an in-memory transition does not.
What I mean by deterministic execution
This is what scafld is for: getting better code from the model by keeping the plan readable, challenging it before execution, and making acceptance depend on evidence. The model’s output remains variable. The process around it should be explicit.
The deterministic part is the process that derives state, the next action, and the acceptance gate from the recorded spec and session. Review records a separate challenge to the change. Finalization consumes the accepted review and the required evidence, then records the result. The implementation agent’s confidence is not the acceptance criterion.
That gives the human something inspectable. What was supposed to happen? What changed? Which evidence was accepted? Which source state did it refer to?
A receipt preserves those answers under the configured trust model. It does not turn an inadequate test into a sufficient one or make a flawed requirement correct. The engineering judgment belongs in the requirement, the review, and the evidence selected to support it.
I want the process to make that judgment harder to skip and easier to inspect. I don’t want another system that produces elaborate paperwork around an unexamined decision.
Know when the process is too much
Not every change deserves this treatment. A sentence, a spacing adjustment, or an ordinary small fix should not acquire an architectural approval ceremony because a tool is available.
Our contract reserves scafld for essential deep changes: architecture, core execution, security boundaries, persistence, and contracts across packages. Ordinary work uses ordinary editing and focused checks.
That limit is part of the design. A process that makes a five-minute correction take an afternoon is not demonstrating seriousness. It is consuming the attention needed for the decisions that actually deserve it.
There is a stopping point for the deeper work too. Once the premise has survived challenge, the required behaviour is demonstrated, and no unresolved issue justifies another pass, finish. Repeating the same review without new evidence does not make it more independent.
A small application still has to own the right things
The October revision of Icey’s webcam example gave me a very literal version of this problem. I wanted a complete WebRTC application in 150 lines. The sample had grown to about 260. At that size, the demonstration was starting to explain its own plumbing instead of the library.
Deleting comments and squeezing statements together would have made the number smaller. It would have left the same amount of work for the person trying to understand it.
The useful question was what the application actually needed to decide. Which input to capture. Which codec to send. When to accept a call, start the stream, stop it, and shut down. The library already had a video-capture abstraction, codec configuration and a packet pipeline. The sample needed to compose those pieces and make their lifetime clear.
In the published change, the capture and encoder setup move together, camera selection becomes a runtime option, and the pipeline survives successive calls. The application starts capture when the session becomes active and stops it when the call ends. On shutdown, capture stops before the graph is torn down. Those decisions are still visible in the sample.
The result is 126 code lines excluding comments and blanks, or 145 lines in the file. The number is satisfying because the application has become easier to explain. You can point to who owns each part of the call.
A first successful frame would have been too weak a test. The browser check used bundled media to make three successive calls through the actual signalling path and decoded H.264 each time. That exercises an application somebody can keep using, rather than a demo that has only been watched once.
What I want to see before execution
I want a plan I can understand, an ownership decision that matches the code, and a reviewer who is allowed to say the work should be smaller, different, or absent.
Then I want execution against that plan, evidence from the real boundaries, and acceptance that does not depend on the implementing agent declaring success.
Once the work is accepted, someone still has to maintain it. That is part of deciding whether it should exist in the first place.