Methodology — spec-first, domain-driven

I don't prompt my agents.
I write a contract with them.

A domain spec. Stories that settle things instead of describing them. A dev agent bound to an architecture it can't route around. A QA agent that replays the story against the deployed app. What runs in production is what was written.

1 🧭 Domain spec PRD + epics the language of the domain decisions, settled 2 📋 Stories written with the PM agent 1 story = 1 contract out-of-scope written down depends_on declared 3 🏗️ Dev agent reads the layou-dev-kit domain → data → UI 1 agent per story 4 🧪 Quality gate lint · tests · arch i18n + widgetbook adversarial review 5 🚀 Release web build + TestFlight the app is deployed not a mock 6 🤖 QA agent replays the story against the live app light + dark PASS → story done FAIL → new story The story the contract

Hover a stage to isolate it. The nodes open the real file, copyable. Drag the graph. Tap an node to open the real file.

The contract

A prompt evaporates.
A story gets replayed.

That's the whole difference. A story can be re-read, reviewed, tested — and six months later it still explains why the code looks the way it does. An agent handed a story has nothing left to guess. And an agent that guesses, invents.

And I don't type it myself. The PM agent grills me: it asks the questions that sting, I settle them, it writes. The story comes out of that session — which is exactly why it holds decisions instead of options. My job here isn't the writing: it's arbitrating, and signing.

story-b2-distance-duration-auto.md
  • status: where the story sits in the loop
  • fr: FR-16 the PRD requirement it covers — traceability runs all the way back to the spec
  • epic: the batch it belongs to
  • dev_kit: ../layou-dev-kit the architecture the dev agent re-reads before writing a line
  • depends_on: what must exist first — this is what makes parallelism safe

What the story settles

  • Decisions, not options. "Routes API (New), because the legacy JS SDK is unusable from Dart." The agent doesn't arbitrate: it applies.
  • Out-of-scope, in writing. That's the line that stops an eager agent from refactoring half the app.
  • The failure behaviour. API silent → fill nothing, keep the field editable. No crash, no silent €0.00.
  • Numbered tasks. T0…T7. A story that won't split is a story that's too big.
Lifecycle
draft ready-for-dev in-progress review done
One story

One agent. One full cycle: spec read, code written, quality gate, release, QA. End to end.

A batch

Several independent stories → several agents in parallel. Agent A on the client picker, Agent B on persistence, at the same time.

The dependencies

depends_on says who waits for what. Two agents only collide when the spec forgot to say so.

The dev agent

An architecture it can't route around

The layou-dev-kit is its own repo, sitting next to the app. The story points at it, the agent reads it before coding. These aren't tips: they're invariants. When an agent goes ×10 faster, this is the only thing keeping the code from going ×10 sideways.

  • 01 presentation never imports data.
  • 02 domain imports neither data, nor presentation, nor Firebase, nor Flutter UI.
  • 03 Root lib/ = shell, router, startup, DI. Nothing else.
  • 04 Every external SDK is wrapped before it reaches app code.
  • 05 Usecase required for writes, side effects, and business decisions.
  • 06 Implementation order: domain → data → app → presentation.
  • 07 UI: screen → connector → organism → molecule.
  • 08 Clean Architecture from day 1. Even for an MVP. Zero throwaway code.
See the architecture as an interactive visualization →

The QA agent

Green tests
don't prove the app works.

So the QA agent doesn't read the code: it opens a real browser on the deployed app and replays the story, screen by screen, like a user. The catch: a Flutter app renders into a <canvas> — there's nothing to click. The fix is one line of architecture: every interactive element carries a stable Semantics(identifier:). That's what makes the app drivable by an agent.

  • Against the deployed app The E2E suite hits the production URL. Not a mock, not an emulator: what the user actually touches.
  • Light AND dark Every screen, in both themes. That's where 80% of visual regressions show up.
  • One suite per epic epic-1-auth, epic-4-calculator, epic-7-acceptance… plus a run-all that chains them.
  • A screenshot at every step The proof is visual. I review a full journey in 30 seconds.
  • What's stubbed is written down The test plan states what isn't built yet → the agent doesn't report phantom bugs.
  • PASS → done. FAIL → story. A bug doesn't drift into a fuzzy backlog: it becomes a story again, with its contract.

Honestly

What this method doesn't do

It doesn't decide for me

The spec, the product trade-offs, the go/no-go: that's me. Agents execute a contract, they don't sign it.

It doesn't replace expertise

If you don't know why a non-lazy list will crawl on an old Android, no agent will volunteer that.

It doesn't forgive a fuzzy story

Vague story = vague code, ×10 faster. The bottleneck isn't the code any more: it's the writing.

It isn't waterfall

A decision lands mid-flight? The story gets corrected, so does the PRD. What's frozen is what's written — not the plan.

Want this loop on your app?

Senior Flutter/mobile, 7+ years, agent-accelerated delivery. 20 minutes to find out whether I'm the right fit.

Book a fit-call