NoteOct 20268 min
Spec Driven Development and How to Build One for Multi Repo Native Engineering (Part 2)
This article talks about my approach to spec-driven development and the repository I built by combining a couple of features from each framework out there.
This article is continuation of my first article [article-link] and talks about my approach to spec-driven development and the repository I built by combining a couple of features from each framework out there.
First article mainly covers how and why I ended up creating this repository to manage four codebases at once.
How it actually works
Here's the short version of what's inside.

Rules and words first
Two files every agent reads before touching anything:
- Constitution: a list of rules that are never broken. Every single one came from a bug that shipped or almost shipped. Breaking one needs a written decision from the product owner.
- Glossary: one name per thing. If the two apps call the same screen two different names, agents will eventually treat them as two different things.
Contracts before features
Before writing any feature spec, I specced the boundaries between the parts: the wireless protocol between the apps and the device, the API, auth, sync, and firmware updates. That's where most cross-platform bugs live. Writing them down also surfaced a bunch of questions nobody had actually answered yet, and each one became a short decision record.
Each contract is a folder: a short README that works as an index (status, what the citations mean, which section lives in which file), then one file per section, like the rules, the endpoints or the message sequences. Sections keep their numbers, so "BLE §4.4" in a bug still points to the right place. An agent that needs one rule reads the index and that one file, not the whole contract.
Pick a baseline
Writing the contracts turned up real bugs in the iOS app that had already shipped, not just in Android. So I had to decide what the spec actually describes. The answer: the iOS app as released. If iOS is wrong, the spec still says what iOS does, and the fix goes into a planned change for later. That gave us three phases:
- Baseline: the spec describes the shipped app.
- Parity: Android gets built to match and ships.
- Joint update: all the planned fixes land on every part at once.
This kept "make Android match" and "make the product better" from getting mixed up.
One folder per feature
Each feature folder has:
spec.md: what it does, written around the common denominator (what every platform shares). No platform APIs.- Notes per part (
ios.md,android.md, ...): how each platform does it and what to watch out for. validation.md: every rule against every platform, marked PASS, FAIL, or BLOCKED.
Rules are short and exact. Each one has a numbered heading, one EARS sentence (WHEN / WHILE / IF ... SHALL ...), and one to three scenarios. Values are exact, like "3 s" or a hex color, never "quickly" or "gold". Rule IDs never get reused, so "R4" in a test, a bug, or a commit always means the same thing.
Trust levels
Every spec says how much you can trust it:
- proposed: agreed, not built yet.
- draft: pulled from existing code. If it disagrees with the code, the code wins and the spec gets fixed.
- verified: checked against specific commits. Now the spec wins, and code that disagrees is the bug.
This is what let me start using it on an existing project on day one without pretending the spec was perfect.
Pick a route
Before any task, the agent says which route it's on: explore, assess, feature, change, bug-fix, or quick. Bug-fix has strict stages: assess (no code edits), fix (the only stage that touches code, starting with a failing test), and test (never edit code to make a test pass). And every bug asks: does the other platform have this too? Most of the time, it does.
The choosing part (a small decision tree and a table of routes) lives in the one file every agent reads first. The steps for each route live in skills, one per route. An agent only loads the bug-fix steps when it's actually fixing a bug. Agents that don't support skills can just open the skill file, since it's plain Markdown in the repo.
Evidence instead of vibes
PASS has to say how it was checked. FAIL says what broke. BLOCKED says exactly what check is still missing, like "needs a real device." Anything only real hardware can prove gets a device test script a person can run step by step. A small validator script runs before every commit and catches the cheap mistakes (missing status lines, duplicate rule IDs, changes that were never synced back) so reviews can focus on the real stuff.
Humans decide, agents prepare
Agents gather evidence, draft specs, and write assessments. Whether an idea is worth building, whether a spec is approved, whether a bug is real: that's the owner's call.
Only read what the task needs
The spec grew fast. After a couple of weeks, the five contracts were 600 to 1,000 lines each, and agents read the whole thing to find one rule. So I split the repo by how often each thing gets read:
- Always read: the agent instructions, the constitution and the glossary. These stay short.
- Read when the task needs it: a route's steps (a skill), a device-test guide (a skill), one section of one contract.
- Rarely read: finished roadmap items (moved to a history file) and old mismatch audits (in their own file per contract).
This sounds like the thing I didn't like about Spec Kit, more files, but the difference is the index. More files only cost you tokens when the agent has to open them all to find something. With an index, it opens one. Looking up a single BLE rule went from reading 607 lines to about 220, and an API rule from about 1,000 lines to about 270.
Templates stayed where they are. An agent only reads a template when it's about to copy it, so moving it into a skill wouldn't save anything.
How I use it day to day
This lets me plan a whole feature in one agent session, then clear the full context and build the feature from the plan using the spec files. No more re-explaining to a fresh session. When the feature's done, the proposal gets moved to the archive and organized, so if we ever need to look back at where we went wrong, it's all there.
To be clear, this doesn't replace reading the codebase, knowing the native platform differences, or testing the real apps. The spec gives the agent a way better starting point. It's not a substitute for engineering judgment or actually verifying things.
Results
I started recording numbers a few weeks in, so this is what I measured from real work, not a controlled experiment.
Every rule in the spec gets a result per platform in a validation.md file: PASS (with evidence), FAIL, or BLOCKED (waiting on a real device). Counting those on Android, starting the day all 20 feature specs existed:
| Date | PASS | FAIL | BLOCKED | Share passing |
|---|---|---|---|---|
| 12 Oct (all 20 specs written) | 25 | 125 | 77 | 11% |
| 14 Oct | 36 | 114 | 77 | 16% |
| 16 Oct | 40 | 110 | 77 | 18% |
| 19 Oct | 66 | 75 | 86 | 29% |
Passing rules went from 25 to 66 in about a week, and failing rules fell from 125 to 75. The 125 FAILs on the first day are not regressions. They are gaps the specs surfaced, each tied to a named rule. The benefit is that "is Android done?" became a count I could watch, instead of a feeling.
What this does not show:
- That the spec made Android faster. Android was being built anyway; the spec gave me the list of what was left.
- That the spec caused the progress. This is progress measured against the spec, not proof of cause.
- Anything about iOS. iOS is the baseline, so it is never marked FAIL.
I also checked tokens used per commit. It fell by about 64% in the Moov repos after the spec, but it fell by about 84% in my other projects over the same weeks, so most of that drop likely comes from something else, such as a newer model and changes in how I work. I am not counting it as evidence for the spec.
What I learned
- Better prompts are only half of it. You also need a way to keep product knowledge and engineering decisions alive between sessions, especially when one product spans multiple repos.
- Put the spec where the agents work. Notion was great for people. Agents need it in Git, versioned and reviewed like code.
- Write the contracts first. That's where the agents disagree the most.
- Be honest about what's real. Describe what the app actually does today, and put the fixes in planned changes.
- Give the spec a trust level. Draft vs. verified lets you start without lying to yourself.
- BLOCKED is a real result. Not proven on hardware means not proven.
- Organize the spec by how it gets read, not how it got written. Keep what every task needs small, and put everything else behind an index or a skill.
- I haven't measured it formally, so I'm not going to throw out a number on time or tokens saved. But I stopped explaining the same feature twice, and that alone was worth it.
In conclusion
Spec-driven development isn't new, but in agentic engineering it's where the software development life cycle (SDLC) meets context engineering: the spec becomes the structured context every agent starts from. It keeps your codebases and your agents in line, so agentic development is smoother and way easier to work with.
The goal is simple: spend less time re-explaining the product and more time building systems that let AI agents work efficiently.