Erik Hanchett deploys spec-driven workflows to tame erratic AI coding assistants
The Problem With Let-It-Rip Coding
Writing code by jumping straight into an editor with an AI tool is tempting. It feels fast. It feels productive. But letting an AI assistant loose without firm boundaries is like handing a production codebase to an eager, unsupervised intern. They will write code instantly, but they will also drift off course.
Spec-Driven Development solves this drift by forcing you to design before you write. You create detailed, structured markdown specifications before touching a single line of application code. This workflow provides the precise context that large language models require to generate high-quality, predictable software.
Prerequisites

To follow this workflow, you need a basic understanding of:
- Markdown syntax for structuring system design docs.
- TypeScript/JavaScript basics for testing.
- Familiarity with running commands in a terminal.
Key Libraries & Tools
- Kiro: An AI-focused development tool available as an IDE or CLI that automates design-to-implementation workflows.
- fast-check: A robust property-based testing library for TypeScript and JavaScript.
- Model Context Protocol (MCP): An open standard designed to connect AI models with external data sources like Jira or databases.
Code Walkthrough: Building Property-Based Specs
Spec-driven development relies on concrete verification. Instead of standard unit tests, we use property-based testing with fast-check to ensure our code adheres strictly to the generated specification.
import fc from 'fast-check';
// The spec: Genre list must be sorted and unique
const filterGenres = (movies: { genre: string }[]): string[] => {
const genres = movies.map(m => m.genre);
return [...new Set(genres)].sort();
};
// Property test verifying the specification
fc.assert(
fc.property(
fc.array(fc.record({ genre: fc.string() })),
(movies) => {
const result = filterGenres(movies);
// Assert uniqueness
const isUnique = result.length === new Set(result).size;
// Assert sorted order
const isSorted = result.every((val, i) => i === 0 || val >= result[i - 1]);
return isUnique && isSorted;
}
)
);
In this block, fc.property generates dozens of randomized movie arrays. It forces the function to handle empty strings, extreme characters, and massive lists, proving the code meets the exact requirements defined in our design spec.
Syntax Notes
When writing specs, use the Easy Approach to Requirements Syntax (EARS) pattern. EARS uses conditional templates to eliminate ambiguity:
When the [Trigger] occurs, the [System] shall [Result].
Keeping your Markdown formatted with clean headers allows AI parsers to correctly break down tasks into sequential steps.
Tips & Gotchas
Avoid the temptation to dump your entire system architecture into a single steering file. Too much context leads to "hallucination soup." Keep your system rules focused and brief. Always inspect the generated task list yourself; you must act as the ultimate human in the loop before letting any code run.
- fast-check
- 29%· libraries
- Erik Hanchett
- 14%· people
- Kiro
- 14%· products
- Model Context Protocol
- 14%· protocols
- Spec It
- 14%· products
- Spec-Driven Development
- 14%· development methodologies

Using Spec-Driven Development for Production Workflows - Erik Hanchett, AWS
WatchAI Engineer // 17:47
We turn high signal in-person events for the top AI engineers, founders, leaders, and researchers in the world into the best free learning opportunities for millions around the world here on YouTube. Your subscribes, likes, comments, speaking, attendance, or sponsorships goes a long way toward making our biz model sustainable indefinitely. We strongly believe this industry deserves a better class of community and that we know how to do this well; we just need your support.