Back to series

Spec-Driven AI-Assisted Development · Article 4

What Software Engineers Still Own When AI Writes More Code

7 min read

Why engineers still own intent, constraints, tradeoffs, verification, and system memory when AI coding agents handle more implementation.

When people talk about AI coding agents, the discussion often gets stuck on one question:

If the AI writes the code, what is left for the software engineer?

I think this is the wrong question.

Writing code was never the whole job. It was the most visible part of the job. It was the part we could point to in a pull request, count in lines, and review file by file.

But the harder part was always deciding what the code should mean.

  • What problem are we solving?
  • What should happen when the input is wrong?
  • Which shortcut is acceptable?
  • Which shortcut will hurt us later?
  • What should be tested before we trust this change?

AI can make implementation faster. But faster implementation doesn't remove these questions. It makes them more important.

Engineers Own Intent

The first thing the engineer owns is intent.

Not the full implementation plan. Not every component. Not every database field. Not every test case.

Intent is the answer to a smaller but more important question:

What should be true when this change is finished?

For a training request feature, the intent is not "create a form." The intent might be:

A colleague can request a training purchase, and Office Management can review it without losing the business context.

That one sentence already changes the work.

It tells us the feature is not only about input fields. It is about a request moving between two sides of the company. It needs status. It needs ownership. It needs enough context for review. It probably needs a history later, even if we don't build it in the first slice.

Lesson: The agent can propose an implementation. The engineer decides the outcome.

Engineers Own Constraints

After intent comes constraints.

Intent says what the change should achieve. Constraints say what the change must respect.

This is where engineering becomes more specific.

A feature is rarely built in an empty system. It has to fit the existing architecture. It has to respect the data model. It has to follow security rules. It has to work with the current team, the current deadline, and the parts of the product that already exist.

For the training request feature, the constraint might be:

A colleague can submit and track their own requests, but they shouldn't see everyone else's requests.

That is not only a UI detail.

It affects the API. It affects the database query. It affects the test cases. It affects what the agent is allowed to generate.

Another constraint might be:

Office Management can review requests, but the requester cannot approve their own request.

Again, this is not just implementation detail. It is a business rule. If we don't state it, the code might still work technically, but the system behavior can be wrong.

Lesson: The boundaries must exist before the code is generated.

Engineers Own Tradeoffs

Constraints define the boundaries. Tradeoffs decide how we move inside them.

This is where the work becomes less mechanical.

A feature can be correct in more than one way. We can build the smallest useful version now, or design for a larger workflow later. We can keep the API simple, or make it more flexible. We can store only the fields needed today, or add structure because we already know reporting will matter later.

The agent can suggest options, but it can't own the consequence of choosing one.

For the training request feature, one tradeoff might be:

Do we build a full approval history now, or only store the current status for the first slice?

Both choices can be reasonable.

A full history gives better traceability. It helps later when someone asks who changed the request, when it changed, and why.

But it also adds more data model decisions, more UI states, more test cases, and more places for the first slice to break.

The simpler version is faster. It can be enough if the goal is to prove the request flow first.

But the engineer has to make that choice consciously.

The problem is not choosing the simple version. The problem is letting the simple version happen accidentally, without knowing what we postponed.

Lesson: The choice belongs to whoever carries its consequences.

Engineers Own Verification

After the tradeoff is chosen, the engineer still has to answer another question:

How do we know this works?

This sounds obvious, but it becomes more important when AI writes more of the code.

Generated code can look complete before it is actually correct. The files are there. The UI renders. The API responds. The tests might even pass.

Passing checks are only useful if the checks match the real behavior we care about.

For the training request feature, verification is not only:

Does the form submit?

It is also:

  • Can the colleague see the request after submitting it?
  • Can Office Management see the same request with the right context?
  • Can the wrong user access it?
  • Does the status change follow the rule we agreed on?
  • Does the system preserve enough information for review?

The agent can write tests. It can run commands. It can fix errors. It can even suggest missing cases.

Lesson: Tests can be generated. Trust cannot be delegated.

In spec-driven work, this is where acceptance criteria matter. They are not decoration. They are the agreement between the intended behavior and the evidence we expect from the system.

Without that agreement, we are only checking that the code runs.

That is not the same as checking that the product works.

Engineers Own System Memory

The last ownership area is easy to underestimate: system memory.

I don't mean the model's context window. I mean the project's memory.

The decisions that explain why the system works the way it works.

In AI-assisted development, a lot of useful reasoning happens inside the conversation. The agent asks a question. The engineer answers. A tradeoff is chosen. A rule is clarified. A test is added because something almost broke.

If that stays only in the chat, the project forgets it.

The code may contain the result, but not always the reason.

This matters because future work depends on old decisions. A new agent, a new teammate, or even the same engineer two weeks later needs to know what was decided and why.

For the training request feature, system memory might include:

  • Colleagues can only see their own requests.
  • Office Management can review all requests.
  • Requesters can't approve their own requests.
  • Approval history is postponed until a later slice.
  • The first slice proves the request flow before adding reporting.

These are not just notes. They are part of the engineering system.

They belong in requirements, design notes, task files, acceptance criteria, or whatever structure the team uses to preserve decisions.

Lesson: The agent can record decisions. The engineer decides what the project must remember.


These five responsibilities form a practical checklist: intent, constraints, tradeoffs, verification, and system memory. To remember what the engineer must do with each one, I use SCOPE.

My engineering checklist

SCOPE

One action for each responsibility engineers still own.

Specify the outcomeIntent Define what should be true when the change is finished. Capture the boundariesConstraints State what the change must respect. Own the consequencesTradeoffs Choose which consequences to accept. Prove the behaviorVerification Check the behavior that matters. Externalize the decisionsSystem memory Preserve what the project must remember.

The engineer doesn't need to control every implementation detail. But the engineer still owns the SCOPE within which the agent works.

The Role Changes, It Doesn't Disappear

At the same time, some parts of software engineering become less valuable.

Not worthless. Just less central.

Boilerplate matters less. Repetitive scaffolding matters less. Translating an obvious requirement into ordinary code matters less.

This is uncomfortable, but I think it is better to say it directly.

If the only value an engineer brings is typing the implementation, that value will keep shrinking.

The role doesn't disappear. Engineers still write code, review it, debug it, and understand the architecture. But they remain accountable for the decisions around that code.

The spec keeps those decisions visible while the agent helps with implementation.

So what does that look like in a real project?

That is where the practical template comes in.