dev-flow — workflow orchestrator
dev-flow does not do the work itself. It is a router: it inspects the project's .workflow/ folder, decides what's next, and tells the user which specialist skill to invoke (or invokes it).
The whole point of this skill is that the user can say "continue building this thing" without remembering which step comes next. The orchestrator reads meta.json, looks at what's already there, and proposes the next move.
When this skill applies
- The user pastes a Figma URL, a product idea, or a vague "let's build X" request and wants the entire pipeline.
- The user opens a project directory and asks "what's next" / "continue".
- The user is unsure which of the dev-flow specialist skills to use.
If the user is clearly inside one phase (e.g., "improve the auth module", "regenerate the pricing page from this screenshot"), call the relevant specialist skill directly — don't route through the orchestrator.
The contract
.workflow/ is the load-bearing convention. Read references/contracts.md before doing anything — it defines the folder layout, the meta.json schema, the phase enum, and which skill owns which file. Do not improvise. If a skill behaves in a way the contract doesn't describe, fix the contract or fix the skill — never silently diverge.
Golden rules (enforced on every project)
Two non-negotiables, defined in full in references/contracts.md §Golden rules — every skill honors them:
- Code is in English — functions, variables, constants, types, file names, DB columns, API fields, comments. Independent of the conversation language (the user may speak Italian; the code is still English). Only user-facing copy is localized (rule 2).
- Every frontend ships i18n from day one — no hardcoded user-facing strings; all copy through i18n keys. Web → next-intl (
stack.i18n = "next-intl"), mobile → the RN i18n stack. Minimum locales English + Italian (stack.locales = ["en","it"], defaulten); more per project. Set at scaffold, not deferred.
Plus ecosystem-first recommended defaults (contract §Recommended default libraries) — e.g. maps → mapcn (web) / mapcn-rn (mobile). Reach for these when the capability is needed rather than hand-rolling.
Stack-aware routing
dev-flow reads meta.json#stack.framework and routes to a stack-specific family of operative skills.
stack.framework value |
family | bootstrap skill | reference |
|---|---|---|---|
next (default if missing) |
existing web skills | design-md-to-app |
(this file) |
expo-rn |
RN/Expo mobile skills | rn-bootstrap |
references/stack-expo-rn.md |
monorepo |
turborepo (web + mobile, shared packages) | monorepo-bootstrap |
references/stack-monorepo.md |
agent |
agent-only — eve at the repo root, no web app | eve-agent |
contract § framework |
When meta.json#stack.framework == "expo-rn":
prd_draftedordesign_extracted→ invokern-bootstrapscaffoldedorpage_generatedormodule_added→ invokern-add-screen(UI) orrn-module-add(backend/infra) orrn-write-tests(tests)feature_complete→ invokern-eas-deploydeployed→ maintenance loop:rn-add-screenfor new features,rn-eas-build-submit-updatefor OTA hotfixes
When meta.json#stack.framework == "monorepo":
prd_draftedordesign_extracted→ invokemonorepo-bootstrapmonorepo_initialized(new phase, mid-bootstrap) →monorepo-bootstrapcontinues (invokesdesign-md-to-appinapps/web/thenrn-bootstrapinapps/mobile/)scaffoldedorpage_generatedormodule_added→ web side:screenshot-to-page/module-add(operate inapps/web/). Mobile side:rn-add-screen/rn-module-add(operate inapps/mobile/). Agent side:eve-agent(operates inapps/agent/— see the agent-engine track below). Cross-cutting:monorepo-add-shared-package,monorepo-sync-typesfeature_complete→ web:vercel-deploy(Vercel). Mobile:rn-eas-deploy. Agent:eve-agentships viaeve deploy(Vercel). Run all that apply.deployed→ maintenance loop on all sides
When meta.json#stack.framework == "agent" (shape ③ — no web app):
prd_drafted→ invokeeve-agent, which is the bootstrap skill here and bumpsphasetoscaffoldedscaffolded→eve-agentin capability mode (tools, channels, skills, schedules, subagents) andeve-registry-portingto borrow from a registry. No phase bump on those — they append tohistoryfeature_complete→compliance-audit(the one gate that still applies — there is no UI forshadscanand no Vercel cost surface forvercel-doctorbeyond the agent's own functions), then ship witheve deploydeployed→ maintenance loop: more capabilities, re-runcompliance-auditafter material changes
Don't offer the web skills here and don't apologise for their absence — design-md-to-app, forms, data-fetching, state-discipline, transitions, shadscan all correctly refuse a project with no frontend. design_extracted, page_generated and module_added are never reached.
If a stack value is not recognized, refuse and ask the user which stack to use. NEVER silently fall back to Next.js when stack.framework is set explicitly to something else.
See references/stack-expo-rn.md for the full RN stack configuration and references/stack-monorepo.md for the monorepo stack configuration.
Workflow
Step 1 — Locate or create the project root
Ask the user for the project's absolute path. If they don't have one, propose ~/projects/<slug>/ where slug is derived from the project name (see contract for derivation rules).
If <root>/.workflow/ does not exist, create it and write a minimal meta.json:
{
"project_slug": "<slug>",
"project_name": "<name>",
"created_at": "<ISO-8601 UTC now>",
"updated_at": "<same>",
"phase": "empty",
"stack": {
"i18n": null, "locales": ["en", "it"],
"framework": null, "ui": null, "auth": null, "db": null,
"payments": null, "deploy": null, "agent": null
},
"history": []
}
Skills downstream require meta.json to exist — never skip this.
Step 2 — Read state and decide the next move
Read .workflow/meta.json. Branch on phase:
Current phase |
Next move (in priority order) |
|---|---|
empty |
prd-from-idea (capture idea + draft PRD). If the user already has a Figma URL handy, can also detour via figma-to-design-md first — but PRD usually comes first for clarity. |
idea_captured |
prd-from-idea (expand PROJECT.md into a PRD.md). |
prd_drafted |
prd-to-tasks if user wants explicit task breakdown; OR figma-to-design-md if user has a Figma; OR image-to-design-md if user has 1+ raster images (PNG/JPG screenshots, mockups, Pinterest pins); OR jump to design-md-to-app if simple project + DESIGN.md will be hand-written. |
tasks_split |
Propose linear-scrum (Setup) to take the project into Linear + set up scrum (default, skip only on explicit opt-out); then figma-to-design-md or image-to-design-md or design-md-to-app. |
design_extracted |
design-md-to-app (this is the natural next step — DESIGN.md exists, time to scaffold). |
scaffolded |
screenshot-to-page if screenshots/ has unmapped images; module-add to wire auth/db/etc.; forms for any form-building request; iterate. |
page_generated |
Propose spec-review on the diff; module-add or more screenshot-to-page runs; forms for forms inside generated routes; data-fetching if any page needs server reads. |
module_added |
Propose spec-review on the branch just landed (cheapest while it is still open — does the diff match PRD.md/tasks.md, and the declared stack?); write-tests to add per-feature coverage (especially after module-add db / module-add auth); more screenshot-to-page; or iterate. When the build is done, advance to feature_complete (all stacks) → compliance-audit pre-deploy gate, then deploy. |
feature_complete |
Propose the three pre-deploy gates: compliance-audit (legal — GDPR/AI-Act, any stack) + vercel-doctor (cost/perf — web on Vercel) + shadscan (UI quality + a11y — web on shadcn). Then deploy: mobile (expo-rn) → rn-eas-deploy; web → vercel-deploy; agent → eve deploy. |
deployed |
Maintenance loop: mobile → more screens via rn-add-screen, OTA hotfixes via rn-eas-build-submit-update; re-run compliance-audit + vercel-doctor + shadscan after material changes; telemetry monitoring. |
| anything else | Treat as empty (forward-compatible). |
Project-management policy (Linear + scrum). Every project is run in Linear with agile scrum unless the user explicitly opts out. When tasks.md exists (phase tasks_split, or prd_drafted once tasks are generated), propose linear-scrum Setup. linear-scrum is also a horizontal capability — invoke it any time for Sync (push new tasks, plan the sprint, report velocity), regardless of phase. It records meta.json#linear + #scrum and appends history, but never bumps phase and never gates progression. For an existing project already partly in Linear, linear-scrum Adopt backfills the link.
Compliance policy (GDPR + EU AI Act). compliance-audit is a horizontal capability — invoke it any time to audit an existing project against the 10-point GDPR/AI-Act risk register (DSAR, consent, EU data residency, retention/PII, AI-transparency, high-risk, sub-processors…) and, on request, apply the safe remediations while flagging the legal decisions. dev-flow proposes it as a pre-deploy gate: when a project reaches feature_complete (before vercel-deploy / rn-eas-deploy / eve deploy), and again in the deployed maintenance loop (re-audit after material changes). It records meta.json#compliance + appends history, never bumps phase, and never blocks deploy on its own — it surfaces findings so the user decides. Especially relevant when stack.agent = "eve" (AI-transparency + memory/residency risks) or the product handles user accounts (DSAR + Apple/Play deletion). Not legal advice — it produces engineering findings + a DPIA template, a DPO/counsel confirms.
Cost/perf policy (Vercel). vercel-doctor is the cost/performance sibling of compliance-audit — a horizontal pre-deploy gate for web projects on Vercel. It wraps the third-party vercel-doctor CLI (scans a Next.js codebase for costly Vercel patterns — caching that defeats the CDN, dead code, function duration, image waste, excessive invocations, config), applies the safe mechanical fixes, and routes the real fixes to the owning skill (data-fetching for caching/invocations, design-md-to-app for images). Proposed at feature_complete (beside compliance-audit) and in the deployed loop. Records meta.json#vercel_doctor + history, never bumps phase, never blocks deploy on its own. Refuses for non-Vercel/non-Next targets.
Review policy (spec + conventions). spec-review reads the change, not the finished artefact — which is what separates it from the three gates. Two axes in parallel sub-agents, never merged: Spec (does the diff implement what .workflow/PRD.md + tasks.md asked?) and Standards (does it obey the golden rules, the declared meta.json#stack, and the discipline skills — with a Fowler smell baseline as the floor). One combined verdict would let either axis hide behind the other: code can follow every convention and build the wrong feature, or build exactly the right feature ignoring the stack the project declared. Propose it when a chunk of work lands (page_generated, module_added), not only before shipping — a spec finding is cheapest while the branch is open. Records meta.json#spec_review; never bumps phase; never blocks. It is not Claude Code's built-in /code-review: that one reviews code generically and knows nothing about .workflow/. Without a .workflow/, spec-review refuses and points there instead.
UI-quality policy (accessibility + fundamentals). shadscan is the third pre-deploy gate, completing the trio: compliance-audit reads the legal surface, vercel-doctor the cost surface, shadscan the UI one. It wraps the third-party @shadscan/cli — a deterministic, read-only static audit of a React/shadcn app across six categories (Foundation, Interaction, States, Accessibility, Forms, Production Polish) scored out of 100 with file:line evidence — applies the high-confidence fixes, surfaces the product decide items to the user, and routes the real corrections to the owning skill (forms for form wiring, transitions for reduced-motion, data-fetching for Suspense/loading boundaries, design-md-to-app for shell/empty-state/metadata, composition-patterns-guide for anatomy). It is the only thing in dev-flow that can mechanically verify our own contract landed — that the prefers-reduced-motion guard transitions mandates and the error association forms prescribes are actually in the built UI. Proposed at feature_complete and in the deployed loop. Records meta.json#shadscan + history, never bumps phase, never blocks deploy on its own. Never optimise for the score — adding unused infrastructure to raise the number is a regression that scores well. Web only (DOM/React rules); refuses for expo-rn.
Animated icons. heroicons-animated adds one Motion-animated Heroicon from the @heroicons-animated/* shadcn registry (ecosystem-first: don't hand-animate an SVG). It requires the motion runtime (module-add motion) and enforces the transitions reduced-motion discipline the raw components lack. Web only; horizontal; no phase bump.
The orchestrator must propose, not impose. After deciding, tell the user the proposed next step in one sentence, and ask for confirmation before invoking (in an autonomous run — §Autonomous runs — write the proposal into the report and continue). Example: "You're at design_extracted (DESIGN.md + 6 screenshots in place). I propose running design-md-to-app to scaffold a Next.js + shadcn project. OK to proceed, or do you want to add modules / change stack first?"
Step 3 — Invoke the right skill
When the user confirms, invoke the specialist skill with explicit input:
- the project root path
- relevant
meta.jsonfields (e.g.,stackfordesign-md-to-app) - any user-supplied input (Figma URL, screenshot path, brand brief)
The specialist skill writes its outputs into .workflow/, updates phase and appends to history in meta.json.
After the specialist returns, read meta.json again to confirm the phase advanced. If it didn't, the specialist either errored or the user aborted — propose the next move accordingly.
Step 4 — Loop
Most projects need multiple specialists in sequence. The orchestrator's job is to keep going: after one specialist finishes, immediately re-evaluate state and propose the next step. Keep looping until the user says "stop" or phase reaches module_added and the user has nothing more to add.
Stack decisions
When transitioning out of prd_drafted and into scaffolding, the user has to choose a stack. The orchestrator should ask once and persist in meta.json#stack. Sensible default-bundle suggestions:
| Profile | framework | ui | auth | db | payments | deploy |
|---|---|---|---|---|---|---|
| SaaS B2B (web, distinctive brand) | next | shadcn | better-auth | neon-drizzle | stripe | vercel |
| SaaS B2B (web, low-maintenance UI) | next | base-ui | better-auth | neon-drizzle | stripe | vercel |
| B2C consumer (web) | next | shadcn | clerk | supabase | stripe | vercel |
| Marketing site | astro | shadcn-astro | null | null | null | vercel |
| Internal tool / enterprise (web) | next | mui | better-auth | neon-drizzle | null | null |
| Editorial / distinctive brand (web) | next | shadcn | better-auth | neon-drizzle | null | vercel |
| Headless + a11y-first (web) | next | base-ui | better-auth | neon-drizzle | null | vercel |
| Mobile app (iOS+Android) | expo-rn | nativewind | supabase | supabase | revenuecat | eas |
| Mobile app, custom backend | expo-rn | nativewind | custom-rest | custom-rest | revenuecat | eas |
| Monorepo (web + mobile) (planned) | monorepo | {web: <shadcn|base-ui|mui>, mobile: nativewind} |
supabase | supabase | revenuecat + stripe | eas + vercel |
Ask the user the project type, propose the bundle, let them override individual choices. Don't ask 6 separate questions when one ("what kind of app?") plus a confirmation gets you there.
Optional agent engine. As part of the same decision, ask once whether the product needs an AI agent engine (an agentic core: tools the model calls, an agent backend, an assistant surface). Default stack.agent = null. If yes → set stack.agent = "eve". The user can also opt in later on demand — see "Agent engine (eve)" below. This is a scope decision, not a pipeline phase.
Optional content layer (CMS). In the same breath, ask once whether the product has content a non-developer edits and the app only reads — a catalogue, pages, articles, FAQs, pricing copy. If yes → stack.cms = "sanity" (contract §Recommended default libraries), wired later by module-add cms (web) or rn-module-add cms (mobile): the hosted Sanity Studio is the admin panel, so the project builds no admin CRUD screens and no admin roles in the transactional database for that content. User-owned data (accounts, orders, bookings) is never CMS content — it stays in db behind RLS. Default null; the user can opt in later on demand ("add a CMS", "aggiungi un CMS").
Topology policy — app first, monorepo next, agent-only for the rare case
⚠️ At init, if the shape is not specified, ASK. Do not derive it. This is a blocking question, not a default to apply quietly: the answer changes the directory layout, every command the user will type, and how much scaffolding stands between them and the first line of product code. Deriving it — "two roles, so two agents, so a monorepo" — reaches an answer without ever asking what the second consumer is, which is the only question that decides it.
The question is short and it is one question, not six:
Is this one app, or does the agent have a life of its own — its own deploy cadence, channels beyond the web UI, or a second consumer that shares its types? If there is no second consumer, it is one app.
Then say the shape out loud, with its reason, and let the user correct it before anything is scaffolded. Getting this wrong is cheap to fix on day one and expensive on day ten.
When an agent is in scope, three shapes are possible and the project decides which. Propose in this order, and say which one you are proposing and why:
| Shape | stack |
Choose it when |
|---|---|---|
| 1 · Single web app (default) | framework: "next", agent: "eve" (agent inside the app) |
The product is the interface. One deploy, no workspace overhead — the ordinary case, and where a frontend developer does their actual work. |
| 2 · Monorepo | framework: "monorepo", agent: "eve" → apps/web + apps/agent |
The agent has a life of its own — its own deploy cadence, channels beyond the web UI, or a second consumer (mobile, a second app) that must share types/tokens. |
| 3 · Agent only | framework: "agent", agent: "eve", no web app |
Every surface is somewhere else — Slack, email, GitHub, Linear — and nothing needs rendering. Vercel Labs' kody-eve-template is this shape. |
The house default is 1, then 2. Reach for 3 only when the product genuinely has no UI, not because the agent feels architecturally tidy on its own.
Don't fossilise the choice — it follows the product, not a habit. Two directions matter:
- A single app can become a monorepo later: that is
monorepo-bootstrap's job, and movingagent/intoapps/agent/is a directory move, not a rewrite. Starting at 1 does not cost you 2. - Choosing 2 up front costs workspace overhead on every command for a second app that may never ship. Ask what the second consumer is; if there is no answer, it is 1.
Say the shape out loud when you propose the stack — "single Next.js app with the agent inside it" is a different project from "monorepo with two deploys", and the user should be agreeing to one of them, not discovering it at scaffold time.
shadcn create parameters (only when ui = "shadcn")
shadcn CLI v4 scaffolds via shadcn create/init with several parameters (the same ones the https://ui.shadcn.com/create wizard asks). When stack.ui = "shadcn", capture them into meta.json#stack so design-md-to-app can pass them to the CLI.
First, offer the preset path. Ask once: "Hai un preset shadcn da ui.shadcn.com/create? (incolla il codice, es. b5owWMfJ8l)". A preset packs the whole shadcn visual system — style, base color, theme, icons, fonts, radius — into one code, made to hand off to agents.
- If yes → set
stack.shadcn_preset = <code>. The preset owns the visual layer: don't ask base color / theme / icons, and the scaffold will pass--presetand skip the DESIGN.md token install for visuals. Still askui_base(the preset may not encode Radix-vs-Base-UI). You canshadcn preset decode <code>to show the user what it contains. - If no → DESIGN.md-first path with the hybrid asking below.
Hybrid policy (no-preset path): explicitly ask only the parameters that matter and that DESIGN.md does NOT own; leave the visual ones to DESIGN.md without asking.
| Parameter | Stack key | Ask? | Values / default |
|---|---|---|---|
| Primitive base | ui_base |
ASK | base (default — Base UI, shadcn's default since 2026-07) | radix | aria (React Aria). DESIGN.md does NOT override it. |
| Icon library | icon_library |
ASK | lucide (default) | radix-icons | tabler |
| RTL | rtl |
ASK only if i18n/RTL relevant | false (default) |
| Template / framework | (uses stack.framework) |
already chosen | next | vite | start | react-router | laravel | astro |
| Base color | base_color |
don't ask — DESIGN.md owns it | scaffold default neutral; DESIGN.md tokens are the real palette |
| Starting theme | ui_theme |
don't ask — DESIGN.md owns it | default null; DESIGN.md tokens override |
| CSS variables | css_variables |
don't ask | stays true (required for token theming) |
| Monorepo | (uses stack.framework="monorepo") |
already chosen | — |
So in practice you ask two things (plus RTL only when relevant): "shadcn su Base UI (default), Radix o React Aria?" (ui_base) and "icone: lucide o altro?" (icon_library). Don't prompt for base color / theme — those come from the DESIGN.md tokens; setting css_variables=true silently. Record the answers in meta.json#stack; base_color defaults to neutral and ui_theme to null for the initial scaffold.
Just before scaffolding, design-md-to-app prints a recap of the full resolved shadcn create config and asks for confirmation (its Step 4 confirmation gate) — including the values derived from DESIGN.md — so nothing is scaffolded on assumed config.
ui = "base-ui"(standalone Base UI, no shadcn CLI) is a different choice fromui = "shadcn"+ui_base = "base". The latter keeps shadcn's component set + blocks on Base UI primitives and is usually preferable; pick standalone Base UI only when the user explicitly wants no shadcn CLI. Seedesign-md-to-app/references/library-choice.md.
ui = "coss" (Coss/UI — the Cal.com design system). A fourth UI choice inside the shadcn/Base-UI family: Coss/UI is installed through the shadcn CLI's @coss/* registry, is built on Base UI, and ships CSS-variable tokens with the same names as shadcn/ui, so the DESIGN.md → tokens pipeline works unchanged. When the user picks Coss (stack.ui = "coss", implies ui_base = "base"), route to the coss-ui skill, which owns the Coss-specific install/add and token reconciliation; design-md-to-app still owns the generic scaffold. It is a deliberate choice with two caveats — Tailwind CSS v4 required and a mixed MIT/AGPLv3 license — so don't default to it; offer it when the user wants the Cal.com aesthetic/DX or an AI-first Base-UI kit. See coss-ui/SKILL.md.
For mobile profiles (framework: "expo-rn"), see references/stack-expo-rn.md for the canonical wiring; the actual modules are wired by rn-module-add after rn-bootstrap scaffolds.
Discipline skills (Next.js 16 web) — horizontal, trigger-driven
Four sibling skills live alongside the phase-driven flow above. They do not bump phase and they apply only to stack.framework ∈ {"next", "monorepo"} + stack.nextjs_version = "16". Invoke them when the trigger fires, regardless of current phase:
| Skill | Trigger | What it does |
|---|---|---|
forms |
User mentions "form", "edit panel", "create dialog", "settings page", "save button" — OR you're about to write a form, useState for field values, raw useForm, hand-rolled dirty tracking, inline toast on submit |
Routes through lib/forms/ shared toolkit. Scaffolds it on first run via forms/scripts/scaffold_lib_forms.py (reads stack.forms = "tanstack-form" or "react-hook-form"). Refuses if Pages Router or pre-16. |
data-fetching |
User is about to add useEffect to fetch, convert a page to "use client" for filter state, add a "use server" getX/listX/findX, or pastes useState + useEffect + fetch |
Walks the 4-rung ladder: Server Component → URL searchParams → Promise<T> + use() + <Suspense> → Route Handler + SWR (last resort). Bans Server Actions for reads. |
state-discipline |
User pastes useState + useEffect, reaches for useState to mirror a prop, derives a value via useEffect + setState, or asks "should I useState here?" |
Walks the 8-rung ladder: derive → URL → lift → query lib → event handler → key reset → useMountEffect → honest useState. Bans bare useEffect. |
transitions |
User says "add a transition / animation", "animate this", "page transition", "stagger these cards" — OR you're about to write an inline transition: / animate={{…}} / @keyframes / a Tailwind duration-[Xms] |
Routes motion through one token layer (lib/motion/) + a curated library, cheapest-tier-first (Tailwind/tw-animate-css → CSS keyframes → View Transitions → Motion). Always ships prefers-reduced-motion. Sits above module-add motion; routes there for Tier-3 spring/layout/gesture. Records stack.motion. |
All four append a history entry per run (no phase bump) and have audit-recipe.md references for "audit my codebase against X" requests. When in doubt about whether to call them: if stack.framework is web-shaped and the conversation touches forms / reads / useEffect / useState / motion, route there.
Agent engine (eve) — an optional, on-demand component
eve-agent is not a discipline skill and not a phase stage. It is an optional product component — a scope decision, like "does this product take payments?". The user opts in, and from then on the project has an apps/agent surface (an eve agent — Vercel's filesystem-first agent framework) that the web app consumes as its AI engine. It is the agent counterpart to design-md-to-app + module-add: where those build/grow the Next.js app, eve-agent builds/grows apps/agent.
There are two moments to opt in:
- At analysis time — during the stack/scope decision (see "Stack decisions" below), ask once: "Does this product need an AI agent engine (eve)?" If yes, set
meta.json#stack.agent = "eve". This promotes the project to a monorepo (apps/web+apps/agent+packages/types) if it isn't one already. - Later, on demand — the user says "add an agent / agent backend / AI core" or names "eve". Same effect: flip
stack.agentto"eve"and bring ineve-agent.
Once opted in, route to eve-agent and let it pick its mode from state: Scaffold mode if apps/agent doesn't exist yet (sets up the engine once), Capability mode if it does (add one tool / skill / channel / connection / schedule / subagent / hook / eval, idempotently).
Why it sits outside the phase line: phase tracks the web app's linear build; the agent has its own cadence (an open-ended "add one capability" loop, often driven by Linear issues, not by dev-flow). So eve-agent records existence in stack.agent and appends to history, but never bumps phase. It owns apps/agent/ exclusively (the orchestrator and the web/mobile skills never write there), and meets the web app at packages/types (re-exported eve session/event types) and the withEve() proxy in apps/web. eve's model calls bill through the Vercel AI Gateway, separate from the build tooling. Choosing the AI Gateway service tier (priority/flex/default) is eve-agent's call, not dev-flow's — see eve-agent/references/eve-scaffold.md §3.
Shipping the product's own agent-skill
Every product this flow builds may end up with an API. One that only its own frontend calls is an implementation detail. One that somebody else's coding agent could drive is a distribution channel — and it needs a single artefact to be usable: a skill file telling that agent how the product works.
Raise it once, at feature_complete → deployed, when all three hold:
- the product has a callable surface that is not only its own frontend —
route handlers under
app/api/, an OpenAPI spec, a public eve agent (stack.agent = "eve"), or an MCP server; and - there is a deployed origin to put in the file; and
meta.json#stack.agent_skillis not set yet.
Then say it plainly, once: "your product is something a coding agent could
drive — want me to write its agent-skill, so your users can install it and use
<product> from Claude Code or Cursor?" If yes, route to
product-to-agent-skill.
⚠️ What it produces belongs to the product, not to dev-flow. The file lands
in <product-repo>/skills/, ships and versions with that product, and is aimed
at whoever installs that repo. It is never added to dev-flow's own skills,
never copied into ~/.claude/skills/, and never listed in install.sh —
the same relationship dev-flow has with the app/ it builds and does not own.
Don't raise it when the API exists only to serve the product's own pages: a skill describing an internal route handler is a lie with a nice table in it.
External skills — suggest, never install
dev-flow ships its skills free. It is also allowed to mention that somebody else's skill exists when a project reaches a point where one would help — the way a colleague tells you which tool down the hall does the thing you just asked for.
references/external-skills.md holds the list: what each one does, the single
moment in a project when it is worth raising, what it costs, and what dev-flow
already does for free instead.
Four rules keep this from turning dev-flow into a paid product:
- Suggest; the user installs. Never run
npx skills addon their behalf, never add one toinstall.sh, never let a dev-flow skill import or require one. - Say the price in the same breath, before the user goes anywhere near a signup page. A payment step must never arrive as a surprise.
- Name the free path we already have, and let the user choose. The suggestion is an option, not a recommendation.
- Only when the work reaches it — never as a menu of possibilities at kickoff.
Nothing in that file is a dependency: delete every row and dev-flow does exactly what it did before.
Autonomous runs — when nobody can answer
Every question in this skill and its specialists — "OK to proceed?", "which stack?", the seven PRD questions — assumes a person at the keyboard. In an autonomous run there is none: a background agent, a scheduled task, claude -p, a batch that rebuilds a project from a brief. There a blocking question is not answered; it stalls the pipeline with nothing delivered.
Detect it, don't guess it. The run is autonomous when the user said so up front ("run it end-to-end without asking", "non chiedermi niente, vai fino in fondo") or when the harness states it is non-interactive. When in doubt, it is interactive — ask.
In an autonomous run every skill follows the same four rules:
- Derive before defaulting. Answer the question from the material at hand — the brief, the transcript, the PRD,
meta.json, the repo, git history. A brief that says "book from the phone" has answered "web or mobile?". Quote the passage that decided it. - Default only where the contract has one. Locales
["en", "it"], the i18n library per stack, the stack bundle for the product type (§Stack decisions),cms = null,agent = null. A default the contract does not name is an invention. - Write every derived or defaulted answer down as an assumption, in the artefact it shaped —
PRD.md§Open questions asAssumed: <answer> — because <source | contract default>, and in thehistoryentry asinputs.assumptions: [...]. Never silently: the user reviews assumptions, not transcripts. - Some questions are never derived. They stop the run with one line — "needs a human: " — and the skill finishes everything that does not depend on the answer:
- the topology shape (§Topology policy: single app / monorepo / agent-only) — deriving it reaches an answer without asking what the second consumer is;
- anything outward-facing or hard to undo:
vercel-deploy,rn-eas-deployand store submission,eve deploy, paid services, deleting data; - credentials and accounts (Supabase, Sanity, Stripe, Apple, Linear): the skill writes
.env.exampleand the out-of-band steps, and stops before the step that needs the key.
The report of an autonomous run opens with the assumptions made — count, then the list — before anything else: that list is what the user has to check, and it is short when the brief was good.
"Propose, not impose" (Step 2) still holds: in an autonomous run the proposal is written into the report instead of asked, and the specialist is invoked without waiting.
What dev-flow does NOT do
- Doesn't do specialist work itself. No PRD writing, no DESIGN.md generation, no scaffolding. If you find yourself doing actual work (other than reading state and routing), stop — call the right specialist.
- Doesn't edit
app/. That's owned bydesign-md-to-appand friends. - Doesn't edit
apps/agent/. That's owned exclusively byeve-agent. - Doesn't make stack decisions silently. Always ask the user, even if a default is obvious — or, in an autonomous run, derive or default it and write the assumption down (§Autonomous runs). Silent is the failure, not unasked.
- Doesn't skip phases. If the user tries to jump from
emptystraight todesign-md-to-app, gently push back: at minimumPROJECT.mdshould exist so the design-to-app skill knows the brand voice.
Bundled scripts
scripts/init_workflow.py <project-root> [--name "Project Name"]— creates.workflow/with a freshmeta.json. Use when the user opts into the orchestrator on an empty directory.scripts/show_state.py <project-root>— prints the currentphase, the files present, and the proposed next step. Use early in every conversation when the user asks "what's next".scripts/update_meta.py <project-root> <op>— mutatemeta.jsonfrom a skill. Three operations:record-artifact --path <p> --produced-by <skill> [--derived-from <p1> <p2> …]— hash a file and record it undermeta.json#artifacts. Skills call this after writing/updating contract files (DESIGN.md, registry.json, generated pages, schema, etc).set-phase <phase>— bump phase forward (refuses regression unless--allow-regress).append-history --skill <name> --inputs <json> --outputs <json> --phase-after <phase>— append a skill run to history.
scripts/check_drift.py <project-root>— diagnostic command. Comparesmeta.json#artifactsagainst the on-disk files and reports:- fresh: file matches its recorded hash, all upstreams match too.
- self-drift: the file has been edited since the producing skill last hashed it.
- upstream-stale: the file is unchanged but a
derived_frominput has drifted (e.g.,DESIGN.mdwas edited →registry.jsonis now derived from a stale snapshot). - missing: the file was recorded but no longer exists on disk.
Exit code is always 0 unless
--exit-nonzero-on-driftis passed (use in CI).
These scripts are JSON readers/writers; running them doesn't make decisions for the user. The artifact-hashing model is the foundation for drift detection — when the user later edits DESIGN.md by hand, check_drift.py surfaces what's now stale, and you (or the user) decide whether to re-run the relevant skills.
When to record an artifact
Record an artifact whenever a skill writes a file that:
- Is part of the dev-flow contract (
.workflow/DESIGN.md,.workflow/PRD.md, etc.), OR - Is a generated config that downstream skills depend on (
registry.json,lib/db/schema.tsinitial scaffold,app/showcase/page.tsx), OR - Is a derivative of an upstream artifact (record
derived_fromso drift detection can chain).
Don't record:
- Temporary files, cache, build artifacts.
- Files the user is expected to hand-edit freely (they'd always show as "self-drift").
- Files produced by external tools (
pnpm-lock.yaml,node_modules).
The cost of recording is one shell-out per file; the benefit is a foundation for resumability and drift checks. Err on the side of recording when in doubt for contract-shaped files.