Specs before agents write code
Scheduled7 min read By NT²
An agent that codes from a vague prompt will invent a product. An agent that codes from a written contract will ship the slice you approved—or stop where the contract ends.
Specs before agents write code
Claim: the prompt is not the product
AI coding agents are fluent. Fluency is not authority.
Left alone with a chat request—“add sync,” “make search faster,” “ship desktop”—an agent will fill every gap with plausible engineering. It will widen the API surface. It will add a second storage path “just in case.” It will treat adjectives as acceptance criteria. The result can compile, pass a few tests, and still be the wrong product: too much surface area, the wrong security boundary, or a feature you never meant to maintain.
NT² Vault is a zero-knowledge, local-first vault. Wrong scope is not only wasted work. It is a threat to invariants you cannot undo later with a polite follow-up prompt.
So the claim is narrow and operational:
Agents implement versioned specifications. Humans own the judgment that those specifications encode.
The specification is the durable contract. Chat is disposable scaffolding. If a decision only lives in a session transcript, the next agent—or the same agent tomorrow—will invent a different product.
This essay is the process deepen after How one person builds and operates NT² Vault with AI agents: not the full lifecycle, but the shape of the contract that makes agent coding safe enough for a security-sensitive product.
Constraint: chat evaporates; agents do not forget inventiveness
Three pressures make “just tell the agent” fail for vault work.
Session memory is not project memory. Yesterday’s thread agreed that salt stays on the device and that cloud auth is a signature challenge, not a password upload. Today’s thread starts cold. Without a written slice, the agent re-derives intent from training priors—generic SaaS patterns that assume the server is helpful.
Ambiguity expands toward convenience. “Helpful” edges want password reset, server-side search, and support tools that open vaults. Agents are trained on codebases that ship those features. If Non-Goals are missing, the agent will “complete” the product in the wrong direction.
Large themes are not shippable units. “Desktop and mobile clients,” “sharing,” and “domain events” are maps. An agent pointed at a map will implement half of everything and verify nothing completely. You need executable slices with checkable done.
The constraint is therefore not “write more docs.” It is: make the unit of agent work small enough to verify and explicit enough that scope creep has nowhere to hide.
Design: maps, slices, and three contract sections
We keep product narrative and architecture elsewhere as long-lived context. What agents implement against is a feature specification: one shippable slice with a goal, a user story for orientation, and three sections that matter more than the prose around them.
| Section | Job for the agent | Job for the human |
|---|---|---|
| Scope | Build only these bullets | Approve what is in |
| Non-Goals | Refuse everything listed; do not “helpfully” add it | Draw the fence before coding |
| Acceptance Criteria | Make each checkbox true and testable | Define “done” without adjectives |
Scope without Non-Goals is a permission to keep going. Acceptance Criteria without Scope is a quiz with no syllabus. Together they are a contract: the agent may claim done only when every checkbox is true and nothing outside Scope appeared in the diff.
Umbrella maps versus child slices
Some capabilities span multiple targets or mechanisms under one product theme: installable clients on different platforms, a sharing framework with several delivery modes, an event model with transport and projections. Treating the whole theme as one agent ticket fails.
We split those themes deliberately:
flowchart TB
U[Umbrella map<br/>shared goal and architecture]
U --> A[Child slice A<br/>executable Scope and AC]
U --> B[Child slice B<br/>executable Scope and AC]
The umbrella is a map: shared goal, cross-cutting refusals, architecture pointers, and an index of children. It does not carry duplicate acceptance criteria. The child is the executable contract for one shippable slice. Implementation pins the child. The umbrella is context—not a license to finish the whole theme in one PR.
Independent slices that do not share an umbrella simply get their own specifications. Either pattern works. Mixing them on the same work—implementing from the map while pretending the children are optional—does not.
Conflict order when documents disagree
When product narrative, architecture notes, and a feature slice pull in different directions, agents need a priority list that does not depend on charisma:
- Hard security rules for the vault (master password never leaves the device, keys non-extractable, salt local, and the rest of the constitution).
- The current feature slice — Scope, Non-Goals, Acceptance Criteria.
- Domain architecture and UX — how storage and screens behave unless they conflict with (1) or (2).
- Product roadmap narrative — intent and status; if intent changed, update the slice rather than coding from the essay alone.
If implementation reveals a bug in the slice, we update the written specification in the same change set. Chat is not the record of record.
The loop around the contract
Specify → plan (read-only) → implement → verify against checkboxes and automated gates → human review against Non-Goals → close by marking criteria and updating status. Planning before edits matters most when the slice touches crypto, sync, or more than a handful of modules. Re-attaching the written slice at the start of a new day or a new agent thread is not ceremony; it is how inventiveness gets constrained.
Trade-off: slower starts, fewer accidental products
Writing Scope, Non-Goals, and Acceptance Criteria before the first agent edit costs time. Splitting an umbrella into children costs more up-front clarity. Humans must approve ambiguity instead of hoping the model “gets it.”
What we give up:
- Chat-speed heroics — the dopamine of “just implement it” on a security surface.
- Umbrella-as-ticket convenience — one prompt that pretends desktop and mobile are the same done.
- Adjective acceptance — “feels fast,” “works well,” “polished enough.”
- Silent architecture drift — decisions that only exist in a merged PR description.
What we gain:
- Checkable done — a reviewer can walk the checkbox list without re-deriving intent.
- Bounded diffs — Non-Goals make over-engineering a contract violation, not a taste debate.
- Handoff — the next session, human or agent, reads the same slice.
- Safer refusal — when an agent proposes password escrow “for recovery,” the Non-Goals and security constitution already said no.
For a one-person product with agent throughput, the expensive failure mode is not “spent an hour writing the slice.” It is “shipped three weeks of the wrong surface and now must unwind a crypto assumption.”
What we refuse
We refuse implementation from a vague prompt with no written slice. If Scope and Acceptance Criteria are not approved, coding is research theater.
We refuse treating an umbrella map as an executable ticket. Maps orient; children ship. Duplicate AC on both layers is how criteria drift.
We refuse empty Non-Goals. “We will figure out boundaries later” is how agents add billing, second encryption layers, or full-table UI loads that undo a paged architecture.
We refuse marking criteria done without evidence. Automated gates catch type and unit failures; security-sensitive flows still need a human walkthrough of unlock, wrong password, export, and lock.
We refuse decisions that live only in chat. If the product intent changed, the slice changes in the repository. The next agent does not inherit tribal memory.
We refuse “convenient” violations of vault security rules to satisfy a checkbox. Fix the specification or the architecture note. Do not teach the agent that §-of-the-constitution is optional.
We refuse scope expansion mid-PR without rewriting the contract. New appetite becomes a new slice or an explicit amendment—not a drive-by module.
These refusals are how agent speed stays compatible with a vault whose cloud layer is blind and whose unlock material never becomes a server oracle.
Contracts that survive the next session
Spec-driven development, for NT², is not bureaucracy theater. It is the minimum structure that lets agents move quickly without inventing a SaaS attic in the sky.
The operating model around that structure—authority tables, approval gates, security vetoes, releases—is in How one person builds and operates NT² Vault with AI agents. This installment is the contract shape inside that model: maps versus slices, and Scope / Non-Goals / Acceptance Criteria as the only honest definition of done.
If you want a vault built so the device stays the place that understands secrets—try NT² Vault or read more at nt2.me.
Last updated 2026-10-18
Related stories
- Security veto is a role, not a vibe
7 min read
- How one person builds and operates NT² Vault with AI agents
10 min read
- Shared crypto packages get a 100% coverage floor
8 min read