Diagram of a decision flowing through implementation to verification on a dark background

AI-assisted engineering: decisions before code

A practical workflow for AI-assisted development: define behaviour, inspect the repository, keep changes reviewable, and verify the assumptions that matter.

An AI assistant can turn a short request into a substantial diff. That is useful when the request is clear. When it is ambiguous, the same speed produces a convincing implementation of a decision nobody actually made. The expensive part arrives in review, when the team discovers that the code answers a different question.

My rule for AI-assisted engineering is simple: make the decision small enough to inspect before making the implementation large enough to maintain. The unit of progress is a verified change in behaviour, rather than the amount of code produced.

Start with a behaviour, then name the boundary

Consider a request to add cancellation to a marketplace. A button and an endpoint are easy to describe. The harder questions are who may cancel, until which order state, and what the customer sees while another system catches up. Leaving those questions open gives the implementation room to invent product policy.

Before asking for code, write a brief that distinguishes the observable result from the mechanism. For a first slice, that might be: a buyer can request cancellation of an unpaid order; paid orders are rejected; repeated requests return the existing cancellation state. Refunds and seller notifications need separate decisions.

  • Outcome: the behaviour a user or operator should observe.
  • Constraints: existing permissions, state transitions, and interfaces that the change must respect.
  • Unknowns: questions that require a product decision or evidence from the repository.
  • Evidence: the examples that will establish whether the result is correct.

This brief also makes disagreement cheap. A reviewer can challenge the paid-order rule before it is spread across a UI, an API, and several tests. A prompt is useful here because it is a compact decision record that can be corrected before code exists.

Ask for a repository map before a solution

A plausible solution can still belong in the wrong place. Ask the assistant to identify the current entry point, the owner of the relevant business rule, and the existing test or integration boundary. Require file references and an explanation of the path a request takes through the application.

Read that map. If the assistant cannot locate the authorization check or explain where order state is stored, there is not enough context to authorize a broad change. Give it a narrower discovery task or resolve the missing decision yourself. More implementation detail will not repair a mistaken model of the system.

An existing convention deserves attention even when a new abstraction looks elegant. Adding a second way to validate requests makes every future maintainer choose between two patterns. The brief should say whether the goal is to extend the current design or deliberately replace part of it.

Separate proposing from changing

For a change with several moving parts, ask for a short proposal first: the files likely to change, the intended behaviour, and the main failure case. A useful proposal names a tradeoff. “Add a service layer” is a shape; “keep cancellation policy in one place so the UI and webhook cannot disagree” is a reason.

Then implement one slice that can be reviewed on its own. In the cancellation example, start with the state rule and its API behaviour. Once those are established, add the interaction that exposes them. This keeps a mistaken assumption from becoming the foundation for a large patch.

Small changes still need complete behaviour. Include loading, rejection, and retry states when they affect the user. Splitting work should make each decision easier to inspect, without hiding unfinished behaviour behind a successful demo.

Verify the assumption most likely to be wrong

A passing typecheck shows that the implementation fits the declared types. It does not establish that the declared behaviour is right. Write acceptance examples independently of the proposed code, then use them to review the result.

  • An unpaid order belonging to the buyer accepts cancellation.
  • An unpaid order belonging to another buyer is rejected.
  • A paid order is rejected without changing its state.
  • A repeated request returns a consistent result without repeating side effects.
  • If payment and cancellation compete, the result follows the agreed state-transition rule.

These examples are a review checklist; a real implementation must turn the relevant ones into checks at the appropriate boundary. The last example is especially valuable because it challenges an assumption that a happy-path demonstration leaves untouched. The right evidence depends on the change: a pure rule may need a unit test, while concurrent writes need verification against the storage mechanism.

Ask the assistant to report what it actually ran, what passed, and what remains unverified. If an integration is unavailable, record that limitation. A claim of completion should be traceable to evidence that another engineer can inspect.

Review the maintenance cost, too

Before merging, read the diff as the person who will debug it later. Check whether the change introduced a dependency, duplicated a business rule, widened a public interface, or added a fallback that hides failure. Each may be justified, but each deserves a reason.

A useful final question is: could a colleague explain this change using the requirement and the diff, without opening the chat? If the answer is no, move the missing rationale into the pull request or the repository. The conversation is working context; maintainers need a durable explanation.

AI assistance is most useful to me when it shortens the distance between a clear decision and a verified result. I would judge that workflow by review effort, defects, and the ease of making the next change. Generating a larger patch is easy to notice; leaving a system easier to understand is the outcome worth pursuing.

For examples of decisions that deserve explicit boundaries, see building a marketplace MVP that survives its own success.

AI-assisted engineering: decisions before code — Vladyslav Dobrodii