The Spec Is Permanent, the Plan Is Garbage
Specifications have an ambiguous form mixing the what, why, and how, which inevitably leads to rot. The intent (“what/why”) evolves, but in a living document, it remains the single source of truth. The implementation (“how”) is wrong by Thursday. Bundled together, the false half drags down the true half.
A human skims a stale document and quietly ignores it. An AI agent doesn’t. It reads a stale implementation section as current fact and confidently builds against code that no longer exists. Spec rot went from an annoyance to a defect generator.
At JupiterGoals, we fixed this by splitting the document in two.
Two homes, one survivor
The living specification holds only the what and the why.
The how goes into a gitignored scratch directory holding checklists, migration notes, and file inventories. These are deleted the moment the change lands - but never before anything permanent in them moves into the spec. Code is the better description of the how anyway. You can’t have stale implementation details in your specs if they are structurally incapable of holding them.
The flow
The pipeline matters as much as the split.
Our orchestrator agent doesn’t draft the spec. It delegates to a product-owner agent running on the strongest reasoning model available. Planning rewards deep reasoning; code generation usually doesn’t.
That agent returns a spec and a plan. The orchestrator extracts tasks as plain text, passing only what’s needed to implementing agents. Agents never read the whole plan. This allows us to cleanly resume tasks from a new session - or even a different harness - when usage limits run out.
Model tiering follows one rule: how expensive is a missed error to catch? A layout bug or type error is cheap. A plausible-looking spec that sends the build down the wrong path for a week is an expensive failure in both token usage and time - that’s where the reasoning model earns its cost.
Keeping the spec true
The split only makes a spec capable of staying true. Four practices keep it true.
Written from the prompt. The orchestrator passes the request to the product-owner agent unedited, then acts as a proxy: the agent asks up to three clarifying questions in one batch, and the answers go back to the same agent so it keeps its context. The interview that would otherwise die in a chat log becomes the spec’s why.
Reviews. We also run a manual /grill-me session 2-3x with a different model to tighten the specifications for a bigger change. This helps catch edge-cases.
Amended in place. Later corrections and discovered constraints are amended in the spec, to ensure we have a single state (always current) for our specifications.
Harvested before deletion. The plan is throwaway; the decisions made executing it are not. If execution uncovers a structural pattern change, the pipeline halts for human approval and an Architecture Decision Record (ADR) review. The clean-up sweep only runs once every box is ticked, ensuring that “delete the how” never quietly becomes “lose the why.”
Automated gates that actually work
A convention nobody enforces lasts about four weeks. We run these checks on pre-commit:
- Heading blocklist: Specs containing
Implementation Planfail the commit. A script enforces the split. - Byte ceiling: Specs over 32 KB fail. Documents that large stop being true because nobody re-verifies them. We used to count by line, but tables and empty lines made that punishing; a byte ceiling is far more representative.
- Coverage gate: Every spec declares a glob of the code it describes. Edit the code without bumping the spec’s last-verified date, and the commit fails.
- Reference resolver: Spec citations are verified repo-wide. Broken links fail the commit.
- Ratio smoke alarm: If rationale outgrows rules by more than 2.5x, the commit fails. Agents shouldn’t have to read an essay just to change a rule.
- Generated index: An auto-generated index lists every spec’s status. Stale indexes fail.
Statuses describe code, not documents
Every spec opens with a status. PROPOSED means the behaviour doesn’t exist yet. PARTIAL names what is missing. Without this, an agent reads a proposed spec as shipped behaviour.
(And the verified date is a calendar date, never a commit SHA. SHAs get orphaned; dates survive rebases.)
Never flag correct code
We originally tried tracking commit volume to flag “stale” specs. It was too noisy, teaching me a sharper rule: never add a gate that fires on correct code. One false positive, and the team learns to reach for the escape hatch by reflex.
The takeaway
The real value is having a specification with the latest state of why / what, and accepting that implementation documentation is a liability. Write plans because they’re useful while building, drain what’s permanent out of them, then throw them away instead of letting them decay.
If your agents keep confidently building the wrong thing, ask yourself: would anything in your pipeline even notice if your specs stopped being true?
Related Articles
Why I Don't Persist Technical Specifications
When refactoring my entire backend and worker architecture to asynchronous serverless tasks, I didn't write a technical spec. Here is why separate technical specs are an anti-pattern, and the 7 homes where technical truth actually lives.
Read article →Forecasting AI Agent Build Time: Using Git History and Task Graphs to Pick Your Parallel Lanes
When LLMs write most of the code, you lose the line-by-line feel for how long work takes. Here is how solo builders and technical leaders can use a task dependency graph (DAG) and git log to forecast build time and parallel lane counts across 412 finished tasks.
Read article →All your goals. One realistic plan.
JupiterGoals fits everything you're working toward into one plan sized to your day. Shrink or swap a step on hard days and keep moving.
Start freeNot ready to sign in? Get product updates by email →