Chapter 7 of 15

Turning Generation Into Validation and Repair

First-pass perfection was the wrong goal; a fast, structured repair loop was the right one. The breakthrough here was accepting that the first pass would sometimes be wrong. Reliability came from making failure observable and repairable, not from pretending a sufficiently clever prompt would remove every runtime mistake.

  • Generate, execute, inspect, repair, repeat
  • Structured failures versus raw terminal output
  • Visual validation using browser screenshots
  • Why first-pass perfection is the wrong goal

The situation

Generated projects frequently failed to build or run on the first attempt because of a missing dependency, wrong config, or framework convention the model guessed incorrectly. In Turning Generation Into Validation and Repair, I wanted to capture the real operating situation rather than describe the problem in abstract terms. What mattered to me was the moment the existing approach stopped being sufficient in normal use, because that was usually the point where the next architectural requirement became obvious.

The naive solution

Try to make the prompt good enough that the model never makes a mistake on the first try. The naive option was attractive precisely because it was faster and easier to explain. I could have pushed further in that direction and probably improved the demo, but it would have optimised the visible symptom rather than the underlying system constraint.

The hidden constraint

No prompt reliably predicts every dependency, config detail, and framework convention correctly across every stack and edge case. This constraint was easy to miss early because it did not show up in the first successful run. It appeared once the workflow had to survive repetition, failure, another user, another provider, or a return visit, which is why I now look for these second-order requirements much earlier.

The decision

Make validation and repair a first-class loop instead of chasing unattainable one-shot correctness. I treated this as an architectural or product decision rather than a prompt tweak. The aim was to create a boundary I could reason about later, instead of relying on model behaviour to remain consistent as providers, templates, and user requests changed.

The implementation

After generation or edits, ran the relevant validation plan (lint, typecheck, test, build), captured structured failure data, fed it back to the agent, let it inspect affected files, applied a targeted repair, reran validation, then committed the successful state. Added visual repair using headless-browser screenshots for layout and responsiveness issues. I also tried to make the implementation concrete enough that the decision could be inspected in code and runtime behaviour. That meant explicit state, explicit policy, and observable transitions rather than a collection of hidden assumptions spread across prompts and handlers.

The tradeoff

Extra latency and compute per generation compared to accepting the first output as final. I did not treat the decision as free. In most cases I was deliberately accepting more engineering, state management, or operational complexity in exchange for a smaller failure surface and a product that could survive realistic use.

The evidence

Failures that previously ended a session (a broken build) instead triggered an automatic repair cycle ending in a committed, working state. I use this evidence as a practical signal, not as a claim that the architecture is universally correct. The useful question was whether the new design changed what the system could reliably do under the conditions that had previously broken it.

The reusable lesson

Design for "generate, check, fix" from the start; it is more reliable and much cheaper to build than chasing a model that never fails. The part I would carry into another build is the decision rule behind the implementation, not the exact technology choice. Vendors and frameworks will change; the underlying question about state, control, isolation, feedback, or user trust is much more reusable.

The consultant's questions

  • What happens today when the model's first output is wrong - does anything catch it before the user does?
  • Do your failure messages give the model (or the human) something specific enough to act on?
  • What assumption in this part of the system would become dangerous if usage or tenant count increased?
  • What evidence would tell me this decision needs to be revisited rather than defended indefinitely?