The earlier article in this series — I Built a Feature in 6 Minutes Using an Orchestrator Agent and MDX Config Files — showed an orchestrator and three subagents shipping a small feature in a single elapsed sitting. That was the discovery moment. This article is about what happens when the work is harder — a real refactor that touches a flow other surfaces in the product depend on. The same pattern still works, but only if you treat the spec, not the code, as the unit of work.
I'll spend this article on a single example: refactoring an existing mortgage application flow so a refinance flow can reuse it. The change took somewhere between 12 and 31 minutes of elapsed time, depending on which subagent you measure. Not minutes of typing — minutes from "I have a spec" to "the diff is ready to review."
The problem — reuse the mortgage application flow for refinance
The product had a working mortgage application flow: applicant intake, credit and eligibility check, document upload, underwriting decision, offer redirect. It lived behind the consumer-facing "Apply for a mortgage" surface, for net-new home loans. Now a refinance surface — where existing borrowers replace their current loan with a new one for a better rate, a shorter term, or to cash out equity — needed the same flow, but with a different entry point (it starts from the borrower's existing loan, not from scratch) and a different post-decision redirect (back to "Manage your loan", not the new-customer welcome screen). The naive approach is to copy the flow and edit the differences. Past me would have done exactly that. The duplicated paths drift, the two redirects start to diverge, and six months later there is a Frankenstein flow nobody owns.
The actual hard part of this work is judgment. Which parts of the flow are stable enough to share? Credit pull, document upload, underwriting decisioning — almost certainly. Property valuation? Refinance reuses an updated appraisal, but the rules differ from a purchase. Refinance also adds steps the original flow never had — a payoff quote on the existing loan, lien handling, sometimes a rate-lock window. Where do you draw the seam so future surfaces don't pay an abstraction tax? Typing was never the bottleneck. Picking the right seam was.
Why I wrote the spec before opening the editor
Spec-driven development means the unit of work is a markdown file, not a pull request. You write the spec first — intent, constraints, success criteria — and the code falls out of it. I used to write specs after the fact, as documentation. Now the spec is the input, and code is the output of running the spec through agents.
The spec for this refactor was a single .md file with five sections: what is changing, what stays the same, acceptance criteria, non-goals, and risks. No diagrams, no API definitions, no code. Just the parts a thoughtful colleague would want before agreeing the change made sense.
| Editor-first workflow | Spec-first workflow |
|---|---|
| Open the editor, start typing | Open a markdown file, write intent |
| Discover constraints by hitting them | Discover constraints by writing them down |
| Code is the artefact | Spec is the artefact; code is generated from it |
| Reviewers read diffs | Reviewers read the spec, then check diffs against it |
| Easy to skip steps you "know" | Hard to skip steps because they sit on the page |
Writing the spec before the code forces every fuzzy thought into a sentence you can argue with.
By the time the spec was finished — twenty minutes of writing, no agent involvement — I had already discovered three constraints I would have missed if I had jumped into the editor. One of them killed an entire branch of the refactor. That alone paid for the spec.
The orchestrator markdown — three subagents
The orchestrator was another markdown file. It pointed at the spec, defined three subagents — analyze, implement, test — and described what each should produce. The orchestrator did not write code. It read the spec and dispatched the three subagents in dependency order.
Think of the orchestrator like a conductor. The conductor doesn't play the violin; the conductor decides when the violin enters and what it plays against. The earlier article in this series went deep on this metaphor for a small feature. Here the conductor's job is harder because the work has phases.
- analyze read the spec plus the existing mortgage application flow, and produced a written plan: which files would change, where the seam would go, what would stay shared. Its output was a plan document, not a diff.
- implement took the analyze output as its input and produced the code changes, in a worktree of its own. It never saw the spec directly — it only saw the analysis.
- test ran in parallel with implement and produced a test plan and the tests themselves, also in a worktree.
The narrow scope is the trick. analyze doesn't get to write code. implement doesn't get to argue about whether the seam is right. test doesn't get to decide what the feature does. Each subagent works inside a small box, which means fewer hallucinations and faster inference.
Skills as reusable context
Two Skills rode along with every subagent: a pre-commit skill that knew the project's lint and format gate, and a react-best-practices skill that knew the rendering and bundle rules I care about. My react-best-practices skill is inspired by Vercel's published agent skills — engineering reference docs Vercel ships for AI agents to consume — and I run their composition-patterns and Next.js skills alongside it in my pinned context. Skills are pinned context — instructions the agent always applies, regardless of which file it's editing.
The mental model is simple. Imagine a senior reviewer who always insists on the same things. Don't ship inline styles. Don't add a third state library. Always run the formatter before declaring done. Skills are how you encode that reviewer once, then attach them to every subagent that runs.
The payoff is consistency. The implement subagent didn't have to be told to run pre-commit; the skill did it. The test subagent didn't have to be told the project's React conventions; the skill enforced them. I stopped repeating myself across runs, and the diffs started looking like they came from the same engineer every time.
MCP — pulling API shapes from two other repos
The mortgage application flow talks to two sibling services that live in their own repositories — a credit-bureau adapter and a document-verification service. Without those repos in context, an agent has to guess at request and response shapes — and guessing is exactly how subtle bugs get shipped. MCP (Model Context Protocol) is the standard for letting an agent pull structured context from outside its current workspace.
I ran a small MCP server that exposed the type definitions and handler signatures from the two sibling repos. The implement subagent could ask the server for the shape of the credit-pull request and get the real definition back, not a hallucinated one. The test subagent could ask for the document-verification response shape and write fixtures that matched it.
The analogy: imagine pair programming with someone who has read every codebase in your company and can recall the right interface on demand. You don't have to brief them. You ask, they answer, you keep moving. MCP is the protocol that turns "every codebase" into a thing the agent can actually query.
How the pattern works
Two tools, two different jobs:
Parallelism in Claude Code
│
┌────┴────┐
│ │
Sub-agents Worktrees
│ │
Parallel Parallel
investigations sessions
Inside one Separate
session checkouts
One branch Different branches
│ │
Use when: Use when:
Short tasks Long divergent work
Returns Needs real files
summary Two realities
in parallel
Both run in parallel. The difference is what they parallelise.
Subagents vs worktrees — what each is for
Subagents run inside one Claude Code session, on one branch. They split the agent's attention into multiple narrow investigations and return a written summary back to the main session. They never produce a working tree of files; they produce text the orchestrator reads and acts on.
Worktrees are a Git feature. A worktree is a separate checkout of the same repository, on its own branch, in its own folder. You can have one Claude Code session in ~/work/repo on main and a second session in ~/work/repo-refactor on refactor/mortgage-refinance simultaneously. Each session has real files on disk that it can edit and run tests against.
| Property | Subagents | Worktrees |
|---|---|---|
| Lives where | Inside one Claude Code session | Separate checkouts on disk |
| Branches | Shares one branch | Each on its own branch |
| Output | A written summary back to the parent | Real files, real diffs, real test runs |
| Best for | Short, narrow investigations | Long, divergent work that must compile |
| Coordination cost | Cheap — they're text | Higher — separate sessions to mind |
The rule I use: if the work fits in a written summary I can paste back into the main session, it's a subagent. If it has to compile, run tests, or live for hours, it's a worktree. The refactor used both — analyze ran as a subagent, implement and test each ran in a worktree.
Watching three agents run in parallel without intervening
The hardest part was sitting on my hands. The implement worktree was generating code. The test worktree was generating tests. The analyze subagent had already returned. Old reflexes — peek, correct, nudge — would have wrecked the parallelism.
I had to trust the spec. If the spec was right and the orchestrator dispatched correctly, intervening mid-run mostly creates incoherent output. The implement subagent has its plan; if I edit the plan halfway through, it has to backtrack. The cheapest path is to let each subagent finish and read its output afterwards.
When all three had finished, I had three artefacts: a plan, a code diff in one worktree, and a test diff in another. Reviewing them felt closer to reviewing pull requests from three colleagues than to writing code. That is exactly the shift spec-driven development is supposed to produce.
What spec-driven agentic dev changes about how you think
The unit of work moves up one level. You no longer think in tasks ("update this file, then that file"); you think in specifications ("this surface should reuse this flow with these two differences"). The orchestrator handles the decomposition. Your job is to be precise about intent.
Reviewing matters more than writing. The agents will write more code in fewer minutes than you can. The leverage is in catching the bad assumption in the spec, not in catching the typo in the diff. If you spend most of your time auditing diffs, you have miscalibrated where the value is.
Debugging shifts up the stack too. When something goes wrong, the question is not "where is the bug in this function" but "where did the orchestrator misread the spec, or the spec mislead the orchestrator." That is a different debugging skill, and it gets sharper the more orchestrators you run.
Four principles, inspired by Karpathy, keep me honest in this kind of work: think before coding, simplicity first, surgical changes, goal-driven execution. I treat them as a personal skill I bring to every feature-build and every system analysis — not specific to Claude Code or to any one project. They are what makes the spec stay sharp, the subagents stay narrow, and the diffs stay small enough to review.
What this means for builders
Treat the spec as the deliverable. Write it before the code, in plain English, with constraints and non-goals explicit. A good spec is review-able by a colleague who has never seen the codebase. A bad spec is the leading cause of bad agent output.
Keep subagents narrow on purpose. Do not let one subagent do analysis and implementation. The split is not bureaucracy — it is what makes parallel work possible and keeps the failure modes shallow. When a narrow agent fails, you re-run that agent with a tighter prompt; when a wide agent fails, you start over.
Invest in your context layer. Skills capture the standing rules a senior reviewer would always apply. MCP captures the cross-repo shapes an agent would otherwise have to guess. Together they are the difference between agents that look smart in a demo and agents that ship correct refactors at midnight. Build them once. Reuse them everywhere.
