← Zach Donnenfield

Method

The story, then the build

Two disciplines that turn out to be one. Before anything gets built I write the story that makes it necessary; then the model writes most of the code and I hold it to a standard it cannot hold itself to.

There are two ways to ship something false: code that looks right, and a story that sounds right.

Generation stopped being the constraint a while ago. I can have a working version of almost anything standing up inside a day, which means the scarce thing is no longer the code and never was: it is knowing what should exist, what must never happen, and how you would tell the difference. So there are two things I check before anything ships, and they turn out to be the same check run twice: once on the reason for the work, and once on the work itself.

One · the story is the spec

I was trained to write before I was trained to ship. My degree is in journalism, and I spent the first part of my career in creative agencies and marketing, where the whole job is finding the true thing inside a pile of material and saying it so that it lands. I did not expect that to be the transferable part of my background. It is the transferable part.

Every decision has a root cause, and in product work the root cause is usually missing from the room. Ask why something is being built and you often get a chain of requests rather than a reason: a stakeholder asked, which came from a deck, which came from a call nobody in the room was on. That is not a why, and a team cannot be aligned to it, because there is nothing there to be aligned to. Getting to the actual cause and then saying it out loud is the first piece of product work on any initiative, and it is writing before it is anything else.

What I write has three parts, which is not a framework so much as the shape an argument already wants to be:

Situation
What is true right now, how long it has been true, and what it is costing while it stays true. Specific enough that someone who disagrees can point at the sentence they dispute.
Complication
Why it is not already fixed. This is the part that gets skipped, and skipping it is what turns a roadmap into a wish list. If the problem were easy, a company full of competent people would have solved it three quarters ago.
Resolution
What is different for the customer once it is solved, stated as a change in their situation rather than a list of features that would exist. The future state is the part a team can actually be motivated by.

The middle one is load-bearing and it is the one people skip. A situation and a resolution with no complication between them is a wish, and everyone in the room can feel the gap even when they cannot name it. Naming what has been in the way is also what makes the resolution believable, because it proves the problem was examined rather than assumed.

Written this way, a spec is not documentation and it is not a ticket. It is the argument for the work, which means it does three jobs at once: it tells the team what to build, it tells whoever controls funding why to keep paying for it, and it survives the meeting where priorities shift and someone asks whether this still matters. The same three parts get retold at different altitudes to different audiences. An engineer needs the complication in detail, an executive needs the resolution in numbers, a customer needs to hear their own situation described accurately enough to trust the rest. But it is one story, and if it changes shape depending on who is listening then it was never true.

This is also the part of the job that looks least like the job. Sitting inside a customer's problem is reporting: you are interviewing, you are checking what you were told against what you can observe, and you are trying to get the story straight before you commit anyone to a plan. Requirements-gathering assumes the requirements exist and need collecting. They usually do not exist yet.

Two · then the build

The written story is what the build runs against, and it is what I hand the model. Models write most of my code. That phrase covers everything from prompting until something compiles to a discipline, and the difference shows up in whether the software survives real use. What follows is four passes, in order.

  1. Generate, then read everything

    The model produces the first draft of nearly all the code, and I read all of it before it lands. Broken code is not the risk; broken code fails loudly. Plausible code is the risk, because it fails quietly, weeks later, in front of a user. Reading everything is slower than trusting the output. It is also the entire difference between shipping a product and shipping a demo.

  2. Evaluate against criteria I define

    The model can write tests, but choosing what deserves a test is judgment, and I keep that. The suite covers what fails silently rather than what fails loudly: a compass bearing interpolated across the 0/360 degree boundary, a projection taken against a heading that changes every few meters, a correction that has to move the right way in both directions and not just one, timestamps surviving a full parse, normalize and store round trip. Several tests are anchored to values I computed by hand, because a model checking its own math is not evidence.

  3. Harden the edges

    Real inputs are hostile. Files arrive truncated, with missing channels, recording gaps and samples that cannot be true. Runtimes refuse the feature you assumed, or ask for reduced motion, or have no worker to hand the work to. The hardening pass is explicit and it is scheduled: a failed input names itself and its reason without disturbing anything else already loaded, every manual correction is validated and reversible, and background work falls back to the foreground rather than disappearing. None of this is glamorous, and all of it is what separates software people rely on from software people try once.

  4. Adversarial review before ship

    Before a feature ships I run a separate pass with one instruction: attack this. Find the input that poisons state, the persistence path that silently wipes user edits, the interaction that steals focus mid-task. The attacking pass regularly finds real defects the building pass was blind to, because the builder and the reviewer should not share a train of thought, even when both are models.

What I own, and what the model does

I own

  • The story
  • The architecture
  • The product decisions
  • The evaluation design
  • The edge-case inventory
  • The taste

The model does

  • First drafts of nearly all the code
  • Refactors
  • Test scaffolding
  • Breadth into unfamiliar territory

The model's column is what makes mine possible. I have shipped work resting on binary file formats, geospatial rasters and realtime 3D that I had not touched before starting, and the model collapsed months of unfamiliarity into days. What it never did was decide that a recorded measurement must not be overwritten by a modeled one, or that an estimate published without a confidence label is a lie of omission. Those are the product, and they were mine.

Where it breaks

A story that outruns its evidence

Being persuasive is a way of postponing disconfirmation. I can win a room for a future state the evidence does not support yet, and the better the telling, the longer a weak idea survives before anyone tests it.

Mitigation The story has to be pinned to something I did not author: measured results, customer language quoted rather than paraphrased, and a stated condition that would prove me wrong. Same instinct as the hand-computed test anchors.

Confident wrong math

Physics and coordinate code is where models are most fluent and least trustworthy. The drafts look textbook and carry sign errors, unit mismatches or boundary bugs.

Mitigation Hand-computed anchors: small closed-form cases where I know the answer independently, wired into the test suite so regressions surface immediately.

Locally correct, globally wrong

Models fix the line in front of them and regress something three functions away, especially in cross-cutting concerns like focus management, state persistence and render loops.

Mitigation Interaction patterns documented as rules in the repo and fed back into every session, so hard-won fixes stay fixed.

Drift

Over a long build, generated code quietly walks away from decisions made earlier.

Mitigation The written story is the anchor. Because intent lives in the repo rather than in my head, I can re-ground any session against what was actually decided, and catch the walk before it compounds.

Trust is the same discipline twice

Every estimate I ship is labeled as an estimate. A modeled number carries a confidence level and a plain statement of what its range is not, because a sensitivity band presented as a statistical interval is a false precision the reader cannot detect. Measured results stay primary wherever both exist, and input quality is reported per channel rather than collapsed into one reassuring score. The same rule governs the story: say which parts are measured and which are believed, and name the thing that would change your mind. An AI-built system earns trust the same way an AI feature does, and a product argument earns it the same way again, by making its uncertainty visible and keeping a person accountable for what ships. That has held for the enterprise applied-AI features I have taken to customers as much as for anything I have built alone, from the disclaimer copy down to the evaluation loop behind it.

Why this is the job

Forward-deployed product work is prototype-speed judgment, and it is the work I do: sit inside the customer's problem until the story is straight, build the credible version while the problem is still live, and be honest about what the system can and cannot do. The two halves of this page are the front and back of that loop. Neither one is preparation for the work. What the method buys is not the speed itself but the right to spend the speed on something that has to hold up.

None of this is a claim about how good the models have got. It is a claim about who answers for the work, for the reason it exists as much as for the code that implements it. That has to be a person. On anything I ship, it is me.