// follow-up post from ...
A factory owner buys a machine that works ten times faster than his employees.
He drops it into the middle of the workshop and switches it on.
Within an hour, it produces hundreds of parts.
Some are correct.
Some are nearly correct.
Some only look correct until somebody puts weight on them.
Nobody can reliably tell the difference.
The drawings are outdated. The measuring equipment is broken. Important specifications exist only inside the head of one senior employee. Quality control is one exhausted person saying:
Looks fine to me.
Production has increased.
Useful production has not.
That is software development with coding agents.
We bought the machine.
Now we need to build the factory.
The Machine Is Not the Factory
Coding agents can already:
- inspect repositories
- implement features
- write tests
- execute commands
- analyze failures
- refactor code
- review diffs
- open pull requests
That is real production power.
It is not engineering maturity.
A factory also needs:
- specifications
- tolerances
- controlled environments
- measuring equipment
- inspections
- stop conditions
- traceability
- accountability
Without those things, an agent is just a very fast developer with incomplete context and no responsibility for the production incident.
We already had developers like that.
Now they scale horizontally.
Stop Writing Wishes. Write Work Orders.
This is not a useful agent task:
Improve customer validation.
Add tests where appropriate.
Do not break anything.
“Do not break anything” is not a requirement.
It is a prayer.
A useful task defines the part:
Reject an empty customer identifier before database access.
Required behavior:
- Reject an empty string.
- Reject whitespace-only input.
- Throw InvalidArgumentException.
- Include "customerId" in the exception message.
Constraints:
- Preserve public interfaces.
- Do not add dependencies.
- Do not modify unrelated files.
- Do not suppress static-analysis errors.
Verification:
- Add a regression test that fails before the fix.
- Run PHPUnit.
- Run PHPStan.
- Run PHP-CS-Fixer in dry-run mode.
- Report commands, exit codes, and results.
No change is a valid result if the defect cannot be reproduced.
That is not clever prompting.
It is a work order.
The agent does not need encouragement.
It needs dimensions.
Get the Blueprints Out of People’s Heads
Critical software knowledge still lives in:
- old tickets
- Slack messages
- abandoned wiki pages
- pull-request comments
- production incidents nobody documented
- comments saying
DO NOT TOUCH - “ask Thomas”
A senior developer may understand the invisible rules around a codebase.
The agent sees files.
It does not see tribal knowledge.
Store durable knowledge (ADRs, Skills, Docs, ...) in predictable places:
AGENTS.md
README.md
docs/architecture.md
docs/domain-rules.md
docs/decisions/
docs/runbooks/
But documentation is not enough.
Make important rules executable.
Do not merely write:
Controllers must not execute SQL.
Add an architecture test.
Do not merely write:
Money uses integer cents.
Encode it:
<?php
declare(strict_types=1);
final readonly class Money
{
/**
* @param int<0, max> $cents
*/
public function __construct(
public int $cents,
) {
if ($cents < 0) {
throw new InvalidArgumentException(
'Money cannot contain negative cents.',
);
}
}
}
The best documentation is a system that rejects invalid construction.
Define Tolerances
Factories do not ask machines to produce “high-quality parts.”
They define tolerances.
Software needs the same thing:
Public APIs must not change.
Domain code must not depend on HTTP infrastructure.
Only repository classes may execute SQL.
No new production dependencies.
PHPStan errors must not be suppressed.
Every skipped verification command must be reported.
A vague instruction forces the model to invent its own definition of quality.
Then everybody acts surprised when it chooses convenience.
Do not ask whether the model was smart.
Ask whether the result stayed inside the tolerances.
Do Not Let the Machine Inspect Itself
An agent saying:
All tests pass.
is not evidence.
It is text generated by the same system that generated the code.
Require:
- exact command
- exact exit code
- relevant output
- tested scope
- skipped checks
- reason for every skipped check
For a PHP project:
composer test
vendor/bin/phpstan analyse --no-progress
vendor/bin/php-cs-fixer fix --dry-run --diff
Where configured:
vendor/bin/infection --min-msi=80
The result must be explicit:
PASSED
FAILED
SKIPPED
NOT AVAILABLE
Not:
Looks good.
Not:
Should work.
Not:
I could not run the tests, but the change is straightforward.
A factory with broken gauges can produce consistently broken products.
Consistency is not correctness.
Add a Stop Button
Agents assume that every task must produce a patch.
That creates ceremonial changes:
- pointless refactors
- speculative abstractions
- unnecessary validation
- comments explaining syntax
- tests that simply repeat the implementation
- unrelated cleanup nobody requested
Sometimes the correct result is:
No change required.
The bug may already be fixed.
The report may be wrong.
Another service may own the failure.
The required external system may be unavailable.
The requested change may make the architecture worse.
Require reproduction first:
Reproduce the reported behavior before modifying production code.
If it cannot be reproduced:
1. Report the scenarios tested.
2. Report the commands executed.
3. Report the observed behavior.
4. Identify unavailable dependencies.
5. Do not create a diff merely to appear productive.
Evidence is progress.
A diff is not.
Review Risk, Not Every Screw
Reading every generated line with equal intensity is not a quality strategy.
It is an attention-distribution bug.
Spend human attention on:
- authentication
- authorization
- money
- migrations
- transactions
- concurrency
- input boundaries
- external integrations
- deleted tests
- weakened assertions
- dependency changes
- rollback behavior
Spend less attention on deterministic work protected by automation:
- formatting
- generated DTOs
- repetitive mappings
- mechanical renames
- schema-generated clients
A decorative screw and a structural bolt do not deserve the same inspection.
That is not laziness.
That is engineering.
But there is no free shortcut:
Reading less code requires testing more behavior.
Reading less and testing less is not industrialization.
It is negligence with better branding.
Stop Measuring Tokens
Lines generated do not matter.
Tokens consumed do not matter.
The percentage of AI-written code does not matter.
Measure:
- successful repository tasks
- human corrections
- reverted changes
- ignored constraints
- regression rate
- review time
- verification cost
- production incidents
- reproducibility
- recovery time
One thousand generated lines may be useful.
They may also be industrially produced waste.
Your repository is the benchmark that matters.
Not the vendor’s multiplier.
Someone Still Owns the Result
When generated code breaks production, responsibility cannot be assigned to the model.
The model does not:
- own the repository
- answer customers
- restore corrupted data
- carry legal liability
- receive the incident call at three in the morning
A real workflow defines:
- who approved the task
- who defined acceptance criteria
- which checks were mandatory
- which checks ran
- who accepted skipped verification
- who reviewed high-risk changes
- who approved deployment
- how rollback works
This is not new AI bureaucracy.
This is engineering accountability that should already have existed.
The machine simply exposes its absence.
Start With One Production Line
Do not build a giant internal AI platform first.
That is how companies spend a year automating work they never understood.
Choose one repeatable task:
- dependency updates
- regression tests
- DTO generation
- static-analysis fixes
- mechanical migrations
- deterministic renames
Then define:
- the input
- the required change
- the constraints
- the environment
- the verification
- the risk level
- the evidence
- the stop conditions
- the approval
- the learning after failure
That is already a software factory.
Small, but real.
The Developer Becomes the Factory Builder
The developer is not disappearing.
The work is moving.
Less value comes from manually typing predictable code.
More value comes from:
- defining correctness
- encoding constraints
- designing architecture
- building verification
- identifying risk
- measuring outcomes
- investigating failures
- deciding when the machine is wrong
A master carpenter should not spend every day producing identical shelf pins.
But somebody still needs to understand material, structure, load, and failure.
Otherwise the factory produces furniture efficiently until somebody sits on it.
The same applies to software.
The agent is not the factory.
The model is not the production system.
Generated code is not automatically the product.
The factory is the system of constraints, evidence, inspection, and responsibility around the machine.
You bought the machine.
Stop admiring how fast it moves.
Build something that can reject its garbage.
Top comments (0)