Introduction
Since Coding Agents became practical, the central design question has shifted a little. It used to be mostly about how we should write code. Now it is equally about how much of that code we should entrust to an agent.
I want to call that degree of entrustment Agenty.
0means we do not entrust anything to the agent100means we entrust everything to the agent
This is not a benchmark for model quality. It is a design parameter for repositories and architectures.
The important point is that higher is not always better.
The goal is not to push an entire repo to 100.
The goal is to decide what should stay near 0, and where high Agenty is actually appropriate.
From that perspective, the *.def.ts / *.impl.ts / *.test.ts split in fuckin-strict-nuxt-dmmf is more than a naming rule.
It is a way of embedding into the repo itself which layers should stay low-Agenty and which layers may safely become high-Agenty.
And the core idea is not tied to Nuxt or Vue. It can be generalized much more broadly.
Agenty Should Be Designed Locally
Agenty is not one global knob for an entire repository. Different layers should carry different values.
I roughly think in three layers:
| Layer | Typical Agenty | Why |
|---|---|---|
def / static rule |
0 ~ 20 |
Rules, types, boundaries, and state transitions should stay deterministic |
spec / declarative test |
10 ~ 30 |
This still belongs to human responsibility, even if it supplements the definition |
impl / wiring |
60 ~ 100 |
If the constraints are clear, this is where agents can do a lot |
The numbers are not mathematically important.
What matters is having a shared language: "def should stay low," "impl may go high."
Where Agenty Should Be Pushed Toward Zero
The first thing I want to say strongly is this: general coding rules and practices should be enforced as deterministically as possible through static analysis.
This is not where we should seek high Agenty.
This is where Agenty should move toward 0.
For example:
formatting
lint rules
type checking
import boundaries and dependency direction
exhaustiveness checks and unreachable-state detection
These should be things the repo itself can reject mechanically.
We should not outsource this to natural-language operations.
Writing guidance in AGENTS.md or in skills can be useful as assistance, but that should not become the law of the repository.
Why not? Because natural-language operation is fundamentally non-deterministic.
the model changes
the prompt changes slightly
the context window changes the interpretation
the skill application order changes the result
If you store your invariants there, the rules themselves become probabilistic.
That is not "raising Agenty." It is simply making your boundaries vague.
My own intuition is that skills should not be the place where a repo's truth is defined. They are more like training wheels that help agents follow truths already embedded in the repo. The truth itself should live in a more static layer.
Static Analysis Is Also Domain Modeling
When people hear "static analysis," they often think only of ESLint or formatting. But the scope is wider than that. Domain modeling also appears at the type level.
That means the order should be:
first write definitions in a static layer
then supplement them with declarative tests
and put implementation last
Here, "definition" does not just mean a type alias. It includes:
state spaces
events
transitions
input/output contracts
error representations
dependency boundaries
These should be described before the implementation whenever possible.
I care a lot about this order. If implementation starts first, both humans and agents drift toward "whatever is easiest to write right now." If definition comes first, implementation is demoted into the job of satisfying a contract.
That demotion of implementation is exactly what makes high Agenty safe.
It Looks a Bit Like SDD, But It Is Not the Same
At first glance, this may look very close to specification-driven development. And in one sense it is. The overall direction is similar: put the specification first, establish agreement before implementation.
But I do not see them as identical. The reason is simple: the operational resolution we need is different.
In a real repository, it is hard to treat vague natural-language specifications as the master source of truth. Natural language is necessary for RFCs and design discussion, and I absolutely value that. But natural language inevitably has these properties:
it leaves room for interpretation
it tends to miss edge conditions
it depends too much on the reader's experience
it becomes probabilistically unstable when handed to agents
That is why I care less about "starting from natural-language specifications" and more about forcing those discussions to eventually collapse into def and spec.
In other words:
RFCs and design discussion can stay in natural language
but the master truth of the repo should be as formal as possible
Do not leave the specification sitting on the altar as prose. Translate it into types, state transitions, declarative tests, and static constraints. Only then do humans and agents truly share the same contract.
That point matters a lot to me. It is not that SDD is bad. It is that in the age of Coding Agents, a specification process whose master artifact remains natural language is not enough. Using probabilistic and ambiguous prose as the final truth of the repository is hard to sustain in the real world.
So the question is not only "should we write specs first?" It is also "how far must we formalize them?"
def / spec / impl Is Framework-Independent
What is interesting in fuckin-strict-nuxt-dmmf is not just that it separates *.def.ts from *.impl.ts.
It is that the separation criterion is based on responsibility rather than framework.
The point is not "split things this way because it is Vue." The same way of thinking can work for React, Svelte, or server-side applications.
At an abstract level, the split looks like this:
feature/
order.def.ts
order.spec.ts
order.impl.ts
Or more generally:
feature/
order.def.*
order.spec.*
order.impl.*
And the meaning of those files is roughly:
def: low Agenty; changing it implies design intent, so agents should not touch it casuallyspec: low-to-medium Agenty; this supplements acceptance conditions and declarative scenariosimpl: high Agenty; this is the part with the most freedom inside the constraint space
Once that split exists, both instructions and operations become clearer.
"Only change
defwhen there is an explicit design change""Fix
implso that it satisfiesspec""Read diffs in
defas specification changes""Read diffs in
implas implementation work"
This is the point where Agenty becomes topology in the repository.
Agenty Is Also a Framework for Education
This is not only about repo design or agent operations. It is also a framework for educating engineers.
To be honest, writing def in a necessary-and-sufficient way is difficult.
It is not an easy task.
What counts as state?
What counts as an event?
Where should we identify things as the same, and where should we split cases?
Which invalid states should be represented explicitly?
Which boundaries should be fixed statically?
Writing these things down formally, without escaping into implementation, takes real training.
But I think that is good. More than that, I think it should be hard.
Because the ability to express domain specification formally before implementation is becoming more important. As Coding Agents become stronger, the scarcity value of "typing fast" goes down. What goes up instead is the value of knowing:
what should be defined at all
what can safely be delegated
which contracts are strong enough for automation
whether generated implementation truly satisfies the specification
In that sense, writing def is not just a preprocessing step.
It trains the actual muscle of formalizing a domain.
This is not totally new. It is close to familiar practices such as "write an RFC before implementation" or "discuss the design before implementation." Coding Agents simply make the importance of that order much stronger.
In the past, even if design was sloppy, humans often reconciled the mess while writing the implementation.
But once agents can generate large amounts of implementation quickly, sloppiness in the definition layer gets amplified downstream.
That is why discussing def first and tightening spec first now has educational weight as well.
I think the question of how we should train newer engineers in the age of Coding Agents is already becoming a real topic, or at least is clearly moving in that direction. If agents write much of the implementation, then what exactly should junior engineers learn?
This framework can be one answer.
write
deffirstmake acceptance conditions explicit in
specbuild
impltogether with agentsreview the result against the contract and the diff
That shifts the focus of training away from typing speed and memorization, and toward:
carving up the domain
designing boundaries
describing state transitions
expressing specifications precisely
verifying generated artifacts
I think that is healthy.
Implementation skill does not become unnecessary.
In fact, good def and spec still require implementation intuition.
But the order changes.
The center of gravity moves toward writing the specification first, then reading, correcting, and evaluating implementation.
And this is sustainable not only for individuals, but for organizations too.
Knowledge stops living only in a senior engineer's head or in the exact phrasing of some lucky prompt.
Instead it accumulates in the repository as static assets such as def and spec.
That helps education, maintenance, and handover at the same time.
Where High Agenty Actually Belongs
So where should high Agenty go?
My answer is: places where multiple implementations are acceptable, and correctness can still be checked mechanically afterward.
For example:
mappings
adapters
UI wiring
API client composition
connecting view and state
domain implementation with lots of boilerplate
These are areas where there may be many possible implementations, but the conditions to satisfy can still be written down relatively clearly. If contract and spec are fixed first, the implementation side can become quite high-Agenty.
By contrast, high Agenty is dangerous in places like:
the state machine itself
exceptional business rules
boundary-value and invalid-state definitions
architectural boundaries
repo-wide coding rules
Those are not things you can safely "fix later." If they drift, every layer of automation after them becomes unstable.
In Web Frontend, Write the VM into def
This matters especially in web frontend.
I think we should revisit an MVVM-like separation. But my interest is not "let's make a ViewModel class." My interest is writing the state transitions of the VM layer as definitions before implementation.
For example:
export type CheckoutState =
| { kind: "Idle"; cart: Cart }
| { kind: "Submitting"; cart: Cart }
| { kind: "Succeeded"; orderId: OrderId }
| { kind: "Failed"; cart: Cart; reason: CheckoutError };
export type CheckoutEvent =
| { type: "Submit" }
| { type: "Resolve"; orderId: OrderId }
| { type: "Reject"; reason: CheckoutError };
export type Transition = (state: CheckoutState, event: CheckoutEvent) => CheckoutState;
Something like this belongs in a file such as checkout.vm.def.ts.
The point is not to freeze how the UI looks. The point is to freeze what states the screen has, and how events move it between them.
That layer should stay low-Agenty. It directly encodes product behavior.
By contrast, the following may tolerate higher Agenty once the contract is fixed:
mapping state into props
splitting components
wiring event handlers
implementing side effects
But there is an important caveat here:
the part corresponding to V in MVVM is still not easy to control well through AI alone.
Layout, typography, spacing, motion, and visual hierarchy are not automatically solved just because the state contract is good.
That layer has a difficulty of a different kind.
I think the V side should often be treated not as an extension of state management, but as a separate source of truth integrated with design tools.
For example:
screen states and transitions live in
VM defacceptance conditions live in
VM speclayout and visual structure live in design tools
code exists to connect those worlds
So Agenty in web frontend is not a single axis. At minimum:
VMcan be split into low-Agenty definition and higher-Agenty implementationVis still hard to steer with AI alone, and should be discussed with design systems and design tools as first-class peers
That is why, in web frontend, I would frame it like this:
VM defshould stay low-AgentyVM specshould stay mediumVM implmay go highViewshould be handled on a separate axis, connected to design tools rather than collapsed into state management
If you do that, the semantics of product behavior remain anchored in the repository through VM, while the visual layer is delegated to a more appropriate design workflow.
In other words, you do not have to force meaning and form into the same box.
This Also Improves Operations and Code Review
This design is not merely AI-friendly. It matters in day-to-day source code operations as well.
First, it gives you separation of specification.
If def and spec are placed in front, the diff separates "what we intended to change" from "how we realized it."
Second, it improves editability by agents.
If the editable region is concentrated in impl, the instruction becomes much simpler:
"implement this while preserving the contract."
Third, it improves reviewability. Reviewers no longer have to read every diff in the same mode.
changes in
defimply specification reviewchanges in
specimply expectation reviewchanges only in
implimply implementation review
This meaning of diffs becomes more important in a high-Agenty world. Agents can write a huge amount of code. Human review bandwidth does not expand at the same rate.
That is exactly why the diffs humans truly need to read must remain as static, declarative, and small as possible. And those static, declarative diffs are also the assets that can be taught, handed over, and maintained sustainably across an organization.
Conclusion
What I want to express with the word Agenty is not merely "how much should we let AI do?" It is a design question about which parts may remain probabilistic, and which parts must stay decisively fixed.
General rules, domain boundaries, state transitions, contracts. These should be kept as static as possible, as type-level as possible, and as mechanically checkable as possible. Then declarative tests should supplement them. Implementation should come last.
High Agenty belongs only where the law of the repository is already fixed, and where exploration inside that law is safe.
The point is not to surrender the whole repository to agents. The point is to let architecture build the sandbox in which agents are allowed to be wild.
I think that is what design in the age of Coding Agents looks like.