The consistency problem

You've experienced this. You write a prompt that gets you brilliant code on Monday. You reuse it on Wednesday for a similar task and get something barely functional. Same model, same task, wildly different quality.

This isn't random. AI models aren't inconsistent — they're precisely consistent with whatever context they receive. The variance you're seeing is variance in your prompts, not the model. Every ambiguity in the prompt becomes a decision point the model resolves on its own, and those resolutions accumulate into outputs that can look completely different from each other.

The consistency problem is a specification problem. A vague prompt is a spec with holes. The model fills those holes with its best guess based on training data — which might be excellent or might be completely wrong for your stack, your constraints, and your definition of "done."

The fix isn't to become a "prompt whisperer" with magical phrasing. It's to understand what information the model actually needs to generate consistently good code — and to provide that information every time.

Context is everything

A model generating code is doing something deceptively complex: it's inferring your entire technical environment from a few sentences, then writing code optimized for that inferred environment. When the inference is wrong, the code is wrong — even if it looks right.

The four context dimensions that determine output quality are:

Most developers provide one of these four. The developers shipping consistently good AI code provide all four, every time. Not because they're being pedantic — because each dimension eliminates a category of bad output.

Mental model: Think of your prompt as a contract. A contract with gaps is a liability — the other party fills the gaps however benefits them. A complete contract is enforceable. Your prompt works the same way: every gap the model fills is a risk you don't control.

The 5 prompt patterns that ship code

These aren't templates to copy-paste. They're structures that encode the context dimensions above into natural-language prompts. Each pattern targets a specific failure mode in AI code generation.

Pattern 01

Role + Task

Assign a precise role before stating the task. The role primes the model's "voice" — it shifts the frame from "generate something that looks like this" to "reason like this expert would reason."

You are a senior TypeScript engineer working on a Next.js 14 App
Router codebase with strict TypeScript and ESLint enforced.

Your task: implement a rate-limited API route for /api/export
that handles burst traffic from a single user without blocking
other users.
Pattern 02

Constraints-First

State what the code must NOT do before saying what it should do. Constraints eliminate a large swath of technically-correct-but-wrong solutions. They're especially powerful for security and performance work.

Constraints:
- No external dependencies beyond what's already in package.json
- Must not block the event loop for inputs larger than 10MB
- Must not expose internal file paths in error messages
- Must pass: npm run build && npm test

With those constraints: implement a CSV parser for the /api/import
route that handles malformed input gracefully.
Pattern 03

Test-First

Ask for the tests before the implementation. This forces the model to reason about acceptance criteria explicitly — and often reveals ambiguities in your own requirements before a single line of production code is written. Pairs perfectly with the Golden Code methodology's BUILD cycle.

Write the test suite for a JWT refresh token rotation function.
Tests should cover:
- Valid token returns new access + refresh pair
- Expired refresh token throws AuthError
- Reused refresh token invalidates the entire token family
- Concurrent refresh requests are idempotent

After I approve the tests, you'll implement the function.
Pattern 04

Error Context

When debugging, give the model the full context stack, not just the error message. The error message is a symptom. What the model needs is the environment, the call stack, the recent changes, and your reproduction steps. This is the pattern that turns 10-minute debug loops into 10-second fixes.

Environment: Node 20, Express 4.18, PostgreSQL 15 via Prisma 5.
Error occurs: only in production, not locally. Started after
deploy on 2026-03-09.

Error: "Cannot read properties of undefined (reading 'userId')"
Stack trace: [paste full trace]
Recent changes: [paste git diff or describe changes]
Reproduction: POST /api/orders with valid JWT but no active session

What's the likely root cause, and what's the minimal fix?
Pattern 05

Iterative Refinement

Treat the first response as a draft. Refine with targeted feedback instead of re-prompting from scratch. Iterative refinement preserves the context the model has already built up — re-prompting throws it away. One well-directed follow-up is worth three fresh prompts.

# After receiving initial implementation:

"The implementation is correct but has two issues:
1. The error handling swallows the original error — I need
   the cause preserved in the thrown error for logging.
2. The retry logic uses exponential backoff but doesn't
   cap at max delay. Cap at 30 seconds.

Keep everything else the same."

What breaks prompts

The flip side of the five patterns is understanding the three failure modes that consistently produce bad AI code. These aren't subtle — they're the same mistakes in different forms.

Vague scope

"Build me an auth system" is not a task. It's a category. The model doesn't know if you want JWT or sessions, if you need OAuth, what your user table looks like, what "auth" means in your domain. It will make assumptions — and it will be wrong about at least two of them.

Fix: define the smallest complete unit of work. "Implement POST /api/auth/refresh — it takes a refresh token in an httpOnly cookie and returns a new access token in the response body. The access token expires in 15 minutes." That's a task with a clear boundary.

Missing stack context

The model has seen millions of ways to implement any given pattern. Without stack context, it picks the most statistically common approach — which might be in a different framework, an older version, or a pattern that conflicts with your existing code architecture.

Fix: include your versions and existing patterns. If you already have a pattern for error handling in your codebase, show it. "Match the error handling pattern used in src/api/users.ts" is more effective than describing the pattern in prose.

No failure criteria

If you don't tell the model what "broken" looks like, it will produce code that looks complete — and may be functionally correct under happy-path conditions while silently failing on anything unusual. The model optimizes for "looks good," not "handles everything."

Fix: state edge cases explicitly. "Handle the case where the upstream API returns 429. Handle the case where the response body is malformed JSON. Handle the case where the user's timezone is null." Each explicit failure criterion is code that gets written and tested, instead of silently missing.

Phase-aware prompting

The right prompt depends heavily on where you are in the development lifecycle. The mistake most developers make is using implementation-phase prompts for design-phase questions — and vice versa.

Phase What you want from AI Prompt posture
Design Surface edge cases, question assumptions, model data structures "What will break at scale? What am I missing? What are the tradeoffs?"
Implementation Write focused, tested, idiomatic code for one module at a time "Implement X with constraints Y. Write tests first."
Debugging Diagnose the root cause with full context, propose minimal fix "Here's everything. What's the likely cause? What's the minimal fix?"
Hardening Think adversarially — find what breaks, what leaks, what fails under load "How would you attack this? What inputs would break it? What's missing?"

This is the insight behind midas_prompt in the MCP server workflow: it generates phase-aware prompts automatically based on where you are in the Golden Code lifecycle. Instead of manually calibrating your prompt posture for each phase, the tool does it for you — with the right constraints, the right context, and the right definition of "done" for that phase.

Before and after: the delta that ships code

The difference between a weak prompt and a strong one isn't length — it's information density. Here's the same task with and without the patterns applied.

Example 1: Implementing a webhook handler

❌ Weak prompt

"Add a webhook handler for Stripe events to my Express API."

✅ Strong prompt

"You are a senior Node.js engineer. Stack: Express 4.18, TypeScript 5, Node 20. Implement POST /api/webhooks/stripe. Constraints: verify Stripe-Signature header using stripe.webhooks.constructEvent, return 200 immediately before processing, enqueue events to a Redis list for async handling. Handle: invalid signature → 400, missing header → 400, unknown event type → 200 (silently ignore). Write the test suite first."

Example 2: Debugging a production error

❌ Weak prompt

"I'm getting 'Cannot read properties of undefined' errors in production. How do I fix it?"

✅ Strong prompt

"Production-only error, started 2026-03-09 after deploying session middleware refactor. Error: 'Cannot read properties of undefined (reading: userId)'. Only occurs on authenticated routes when the request has a valid JWT but no corresponding session in Redis (TTL expired). Stack trace: [trace]. What's the root cause? Minimal fix that doesn't change the session schema."

The weak prompts will get you something. The strong prompts get you something you can ship. The delta isn't cleverness — it's the four context dimensions applied consistently.


Prompt engineering for code isn't a dark art. It's applied specification. The model will give you exactly what you ask for — so the real work is learning to ask with precision. Role + task, constraints-first, test-first, full error context, iterative refinement. Apply those patterns with phase awareness and your AI tools stop being lottery tickets and start being force multipliers.

The developers shipping consistently good AI code aren't more creative with their prompts. They're more disciplined. Treat the prompt as the spec, and you'll stop being surprised by what you get.

Automate phase-aware prompting

Install midas-mcp and let midas_prompt generate context-rich, phase-aware prompts for your current task — with the right constraints, stack context, and failure criteria built in automatically.

npx merlyn-mcp click to copy

Also read: Ship AI Code 10x Faster Without Skipping the Important Parts →