Most teams do not judge an AI coding agent by its model. They judge it by the handling around a change: who signed off on the plan, where the work actually ran, whether it can pick itself back up after a restart, and whether anyone will know later why a call went the way it did. The running example throughout this guide is Agent Smith, developed daily across more than a thousand specs, and the differences it reports cluster in four places users eventually feel — verification, isolation, continuity, and record.
The working pattern is specification-driven end to end: each change starts as a written spec inside your repository, a fresh reviewer checks that spec against your code before anything is built, the agent builds on its own branch and worktree, and the commit lands only when your checks pass. Read as an application pattern rather than a tool demo, it answers six routine complaints.
| Complaint you hear in delivery meetings | What the spec-first flow does about it |
|---|---|
| Nothing checked the plan before the machine ran | Verified before the build: a reviewer with no prior involvement compares the spec with the code, and before the commit a gate performs your checks. |
| Two agents collided on the same work | Isolation: each spec receives its own branch and worktree, and ids drawn from the clock keep two agents from taking the same one. |
| The agent stops every ten minutes to ask | Continuity: open questions are settled during review, so the agent continues to its done criteria instead of coming back with more questions. |
| Pull requests all look different | Structure: a one spec, one branch, one commit pattern gives pull requests a consistent shape, whether they carry a single change or a whole series. |
| Restarting the machine loses the thread | Resumable state: the project state lives in context.yaml, so after a restart of the machine or agent the work resumes at its stopping point. |
| Nobody writes the reasoning down | Explanation as a side effect: each choice is recorded beside the code, noting what it beat and why. |
Four skills carry a piece of work through its own branch and worktree. Each one leaves a file behind for the next step and for whoever reads the history later — which is exactly what makes the workflow reusable by a team instead of living inside one person's chat.
| Skill | Where it sits in the workflow | What it leaves behind |
|---|---|---|
| create-spec | Before any code exists: goal, steps, facts with file and line, and what done means | specs/planned/{id}.yaml |
| review-spec | Resolves every citation, then asks a fresh reviewer who never saw the chat to challenge it | BUILD · CUTS · REFUSE |
| apply-spec | Builds contracts, code, wiring, and tests according to the project's own rules | decisions/{id}.yaml |
| deliver-spec | Makes one commit through the gate, pushes it, and opens the pull request | feat: … ({id}) |
Set the ground rules once. /spec-first:bootstrap-project reads your code and writes stack, rules, and required checks from what it finds. From that point on, each spec adds one line of state.
Write the spec first. create-spec records the goal, the steps, the facts with file and line, and the done criteria before a line of code exists.
Have the plan challenged. review-spec resolves every citation and hands the spec to a reviewer with no conversation history, who reads the code as it is rather than as the spec says it is.
Build to the criteria. apply-spec builds contracts, code, wiring, and tests against the project's own rules, logging each non-obvious choice as it goes.
Commit through the gate. deliver-spec makes one commit through the gate, pushes it, and opens the pull request.
Read the record before you start again. The record grows with every spec and is read before every step: specs/ stores every spec from planned to done with facts and done criteria; decisions/ stores what each spec chose, what it chose over, and why; memory/ stores what you told the agent once, so you do not have to say it twice.
A bigger change can be broken into multiple specs. /spec-first:deliver-series reviews the set, builds the groups that share no file at the same time, verifies the merged tree, and opens one pull request.
A worked run, deliver-series 2026-10-27-8a3f, shows the shape of this: the queue reports 5 specs and 3 groups while building, the run uses 3 worktrees in parallel, and the result lands as PR #42.
| Spec | Group | Dependency | Build group |
|---|---|---|---|
| a | tickets-provider-contract | requires nothing | 1 |
| b | tickets-github-provider | requires a | 1 |
| c | tickets-jira-provider | requires a | 1 |
| d | settings-provider-page | requires nothing | 2 |
| e | ci-restore-cache | requires nothing | 3 |
The rule behind the grouping is simple: specs that share no file are built together, while specs that depend on one another share a group. Every spec commit still passes through the gate.
A REFUSE costs one spec. Without review, the same mistake would cost the branch. That single sentence is the business case for putting a check in front of the build instead of behind it.
| Spec | 2026-10-27-8a3f |
| Applies to | server |
| Branch | spec/8a3f |
| Goal | Ticket providers so pipelines can pull work from GitHub and Jira. |
| Facts, read in the code | Pipelines take work only from the CLI today Program.cs:40-58 Config already carries a tracker section AppConfig.cs:12-19 |
| Decision | Adapter over repository: read-mostly data, no unit of work needed. |
| Done when | GitHub provider returns tickets end to end Jira provider behind the same interface verify: stages green |
REVIEWED · BUILD fresh reviewer · 27 OCT. The review is dated 2026-10-27.
evidence resolves: 1 spec
BUILD WITH CUTS: the spec holds once two steps change.
CUT 1: Jira needs a second auth mode the config can't hold yet (AppConfig.cs:15). Move it to its own spec.
CUT 2: Paging is missing, because GitHub returns 30 issues per page (GitHubClient.cs:88). Add a done criterion.
A script opens each file and line the spec cites, and any claim nobody checked in the code must be listed as an assumption. A new agent with no conversation history then reads the code as it is, not as the spec says it is. The verdict is BUILD, BUILD WITH CUTS, or REFUSE, and every finding names a file and a line.
Documentation is not postponed to a later sprint. While the agent builds, it logs each choice that was not obvious — what it chose, what it chose over, and why — into one file per spec that sits next to the code.
decisions/2026-10-27-8a3f.yaml
spec: 2026-10-27-8a3f
decisions:
category: TradeOff · chose: "Raw HttpClient for the GitHub API" · over: "Octokit" · reason: "Three megabytes of dependencies for four calls."
category: Architecture · chose: "One ITicketProvider per tracker" · over: "A generic REST mapper" · reason: "Each tracker pages and authenticates differently; the mapper would leak it."
No wiki has to be kept alive: cat decisions/*.yaml is the project's reasoning, spec by spec, in the same history as the code it explains.
Memory stores what git cannot tell — how the operator wants things done, a constraint outside the repo, or a pointer elsewhere — as one fact per file with one line in an index.
Back in thirty seconds: restart the machine, restart the agent, open context.yaml, and it knows what is done, what is active, and what comes next.
When a commit names its spec, the commit gate runs every verify stage declared in contexts. If all stages are green, it commits. The first red stage blocks the commit and sends its output back to the agent.
git commit -m "feat: ticket providers (2026-10-27-8a3f)"
The id in parentheses triggers the gate. -F <file>, -C, and --amend --no-edit are gated too.
✓ build dotnet build
✓ tests dotnet test
✕ web cd web && npm test
PASSED means every stage is green and the commit is allowed. BLOCKED means the first red stage stops it and its output goes back to the agent.
# spec-first-gate.log · one line per spec commit
2026-10-27T09:14:02Z blocked 2026-10-27-8a3f /work/repo a1b2c3d web
2026-10-27T09:31:47Z passed 2026-10-27-8a3f /work/repo a1b2c3d build,tests,web
Two lines, seventeen minutes apart, are the whole audit trail for one spec. A spec commit with no line in the ledger never met the gate; a project that already has its own gate says gate: project, and the plugin steps aside.
You need one specific agent product. No. The Claude Code plugin runs the steps as commands, but Codex, Cursor, Copilot, or a terminal can follow the same files through AGENTS.md, and a git commit-msg hook runs the same commit gate in every clone where it is installed.
The plan is the truth. The reviewer reads the code as it is, not as the spec claims; anything not checked in the code has to be listed as an assumption.
Documentation can wait. The decision file is written while the agent builds, so there is no wiki to keep alive afterwards.
One agent run must equal one pull request. A single change gets a consistent one spec, one branch, one commit shape, while deliver-series takes a whole series of specs to one pull request.
Context lives in the chat. State lives in context.yaml, plus specs/, decisions/, and memory/, so a restart resumes rather than restarts.
In Claude Code, the plugin handles bookkeeping and runs the gate. Codex, Cursor, Copilot, and other agents follow the same files through AGENTS.md, while a git hook can run the same gate.
/plugin marketplace add holgerleichsenring/specification-first-agentic-development
/plugin install spec-first@specification-first-agentic-development
Then run /spec-first:bootstrap-project. It reads your code and writes the contexts and rules from what it finds.
create-spec writes the spec on its own branch and worktree.
review-spec performs the evidence check and the fresh reviewer's verdict.
apply-spec builds the spec up to its done criteria.
deliver-spec commits through the gate and opens the pull request.
deliver-series takes a whole series of specs to one pull request.
log-decision, update-project, and bootstrap-project handle decisions, upgrades, and setup.
An agent following the method can be asked to create the contexts, specs, decisions, and memory directories, then write AGENTS.md from the templates. Templates are available at https://github.com/holgerleichsenring/specification-first-agentic-development/tree/main/templates
Create .{project}/contexts/default/context.yaml and coding-principles.md. Fill them from the code as it is: stack, architecture, limits, conventions, and the commands that build and test it as verify: stages. Invent nothing.
Create .{project}/specs/planned, active and done, .{project}/decisions/, and .{project}/memory/MEMORY.md.
Write AGENTS.md from templates/prompt.md, with .{project}/ filled in.
Add "gate: git" at the top level of that context.yaml.
Codex, Cursor, and Copilot read AGENTS.md when a session starts. It holds the read order and workflow, and every step says how to do it by hand, including the review brief for a fresh session.
Clone the spec-first repository once, then run python3 <clone>/hooks/install-git-hook.py in each clone of your project. The commit-msg hook runs verify: stages on every commit that names a spec, from any agent or the terminal. git commit --no-verify skips it. The evidence check is skills/review-spec/scripts/check-evidence.py in the same clone and needs PyYAML.
Agent Smith is the open source agentic software factory: a ticket goes in, a verified pull request comes out. It was built entirely with this method, and the method grew from building it — everything in the plugin ran there first.
1,300+ specs done
1,190+ decision files: chose, over, why
650+ specs through the gate
Counted in the Agent Smith repository, October 2026.
A way of working with AI coding agents where every change starts as a written spec in your repository; a fresh reviewer checks the spec against your code before anything is built, the agent builds it on its own branch and worktree, and the commit lands only when your checks pass.
The spec drives the work from start to finish: it names the goal, the facts it rests on with file and line, the steps, and the done criteria, and the agent builds to exactly that. Spec-first agentic development is specification-driven agentic development where the spec is reviewed against the code before the first line is written.
No. The plugin runs the steps as commands there; elsewhere Codex, Cursor, Copilot, or a terminal follow the same files through AGENTS.md, and a git commit-msg hook runs the same commit gate in every clone where it is installed.
You still describe the feature in your own words and talk it through. After that, the agent works from a reviewed spec instead of from the last prompt, logs each decision with its reason, and a commit lands only when your build and tests pass.
A one-sentence goal, the facts it rests on with file and line, the steps, what an upgrade costs an operator, and the done criteria. Choices made while building go into a separate YAML file next to it.
Nothing. The method, the templates, and the Claude Code plugin are MIT licensed.
Run one ordinary change end to end — create-spec, review-spec, apply-spec, deliver-spec — before attempting a series.
Bootstrap once and fill the contexts from the code as it is; invent nothing, because every invented fact becomes a false citation later.
Make done criteria observable, the way the example spec does: a provider returns tickets end to end, a second tracker sits behind the same interface, verify: stages green.
When review finds something the current config cannot hold, move it to its own spec rather than stretching the branch.
If behavior such as paging is missing from the plan, add it as a done criterion instead of leaving it to be discovered at demo time.
Treat the ledger as the audit: a spec commit with no line in the ledger never met the gate.
Let decisions be written during the build; a category, a choice, what it beat, and a reason are enough for the next reader.
Essay: The Why Never Gets Written Down, codingsoul.org · April 2026
Essay: Next Level Vibe Coding, codingsoul.org · April 2026
For teams evaluating where an AI agent earns its place in a delivery workflow, the useful takeaway is not the tooling but the ordering: a plan a stranger can reject, a workspace nobody else is sharing, a commit that cannot pass a red stage, and a reason file written while the work is still warm. Adopt the order and the artifacts follow; adopt only the commands and you are left with a faster way to produce unreviewed code.