A spec is not pure because it is detailed. A spec is pure when its parts stop fighting each other.
Author: James Phoenix | Date: June 2026
The Small Prompt That Changed the Plan
I was working through a design doc for link tracking and shortlinks. The idea started simple: rewrite links in scheduled social posts, redirect through a short domain, record clicks, and feed those clicks into analytics.
Then the plan got better. I added per-channel settings, platform hard-gates, in-media shortlinks, QR codes, a queued click write path, and richer attribution. Each change was reasonable in isolation. The problem was that the document still contained fossils from earlier versions.
The architecture diagram still described direct per-click API ingestion. A later scaling section said Cloudflare Queues. The service section deduped by scheduled_post_id and target_url, but the media attribution section needed distinct slugs for the same target URL in different placements.
So I asked the agent to read the spec top to bottom and find contradictions.
That prompt is now part of my human-in-the-loop checklist.
Why Plans Accumulate Contradictions
LLM-assisted planning is iterative. That is the whole point. I ask a question, the model explores, I push back, it updates, I add a constraint, it refines the design. But long iterative plans have a specific failure mode: the model tends to append and locally edit rather than globally reconcile. When a new decision overrides an old one, the nearby paragraph changes. The rest of the document may not.
Old assumptions stay alive in diagrams, interface sketches, open questions, invariants, tests, and security notes. The model does not naturally treat the document as a single constraint system unless I ask it to.
Humans have the same problem. I anchor on the newest decision. If the latest section says “Cloudflare Queues”, I mentally assume the whole plan now says that. It might not.
Contradictions are usually caused by successful refinement, not bad thinking.
The better the conversation gets, the more likely earlier text has been superseded.
What I Mean by Spec Purity
A pure spec has no internal fights. Its architecture, interfaces, invariants, migration notes, tests, open questions, and product language all point at the same system.
Agents execute the written surface, not my private intent. A human engineer might notice the conflict and ask which version is current. An agent may choose whichever paragraph is nearest, clearest, or most convenient.
In other words: a contradictory spec is a nondeterministic prompt.
It gives the model multiple valid trajectories. If the code comes out wrong, the agent may have obeyed the stale paragraph.
The Contradiction Pass
The contradiction pass is a dedicated review step after the plan feels complete and before implementation starts.
The prompt is simple:
Read this plan top to bottom.
Find internal contradictions, stale assumptions, unresolved decision drift,
interfaces that no longer match the data model, and open questions that were
already decided elsewhere.
Do not improve the design yet. First list the conflicts.
Group them by theme. For each one, quote or summarize both sides of the conflict
and state which decision should probably win.
The important part is “do not improve the design yet.” I want an audit before another rewrite. First expose the constraint conflicts. Then resolve them deliberately.
After that, I ask it to apply the fixes, then run the same pass again.
The loop is:
- Write or refine the plan.
- Ask for contradictions.
- Resolve the contradictions in the spec, not just in chat.
- Ask for contradictions again.
- Only then decompose into tasks or start coding.
This catches the kind of bugs that tests find too late: wrong boundaries, wrong data model assumptions, wrong idempotency keys, wrong platform rules, wrong ownership of responsibilities.
Human-in-the-Loop Means Adversarial Timing
Most human-in-the-loop workflows are framed around approval. The agent proposes a plan, the human approves it, the agent executes. That is useful, but too weak.
Approval asks: “Do I like this?”
Contradiction review asks: “Can this plan be true all at once?”
That is a much better question.
My highest leverage is choosing when the agent should switch modes. Explore mode expands the design space. Planning mode organizes it. Contradiction mode attacks the plan as a constraint system.
This is where planning and validation meet. The contradiction pass validates the plan before the plan becomes code.
It also pairs naturally with adversarial framing. A normal assistant preserves momentum. A contradiction hunter is allowed to slow the session down while the cost of change is still one paragraph.
The Shortlinks Example
The shortlinks spec surfaced eight useful contradictions in one pass. Four changed the implementation path.
The first was click transport. Early sections said the redirect Worker would call the API directly with ctx.waitUntil(fetch(...)). Later sections said it would enqueue events to Cloudflare Queues for batch insert. Both cannot be the hot path.
The second was credential language. Some sections made HMAC mandatory. Others treated a shared bearer secret as acceptable.
The third was idempotency. Deduping by (scheduled_post_id, target_url) sounded clean until media placements arrived. The same download URL can appear as a caption link and an in-video QR code, and those need separate slugs.
The fourth was platform language. “Instagram has zero tracking value” was true for caption auto-rewrites and false for in-media QR codes. The fix was to narrow the claim.
None of these were implementation bugs. They were pre-implementation contradictions. Catching them in the spec removed ambiguity before code existed.
The Practice I Want to Keep
I now treat contradiction-finding as a required final pass on any serious agent-written plan.
The prompt I want is not “make this better.” That is too broad. I ask where the plan contradicts itself, which sections are stale, which interfaces no longer match the data model, and which open questions have already been answered.
This is cheap because the LLM has the whole plan in context. LLMs are good at comparing text. They can scan for semantic drift faster than I can after an hour discussing the same plan.
The human job is not to outsource judgment. I still choose which decision wins. The agent finds the fault lines. I resolve them.
The best time to ask an LLM for contradictions is right after the plan feels finished.
That is the moment my confidence is highest and the document is most likely to contain stale assumptions from the path I took to get there.
Related
- Verified Spec-Driven Development – Adversarial review before implementation
- Highest Leverage: Plans & Validation – Why planning and validation are the human leverage points
- Assume Wrong by Default – Repeated verification passes over LLM output
- Techniques for Overcoming Chat Psychosis Bias – Prompt frames that produce sharper critique
- The Two Camps of Agentic Coding – Spec-driven agents versus conversational coding

