Designing Prompt Pipelines
For a new (greenfield) project, create three prompt files:
context/prompts/
├── 001-generate-specs-from-refs.md # refs/ -> kits/
├── 002-generate-plans-from-specs.md # kits/ + impl/ -> plans/
└── 003-generate-impl-from-plans.md # plans/ + kits/ -> src/, tests/, impl/
Each file follows this skeleton:
Markdown# 00N: {Phase Name}
- Framework: {FRAMEWORK}
- Build command: {BUILD_COMMAND}
- Test command: {TEST_COMMAND}
Read {INPUT_DIR}. This is the source of truth.
{What to produce, where, in what format}
- {verifiable condition}
- {build/test passes}
For a rewrite (reverse-engineering old code), start with 6 prompts (001-006); see Workflow.
Progress:
- Step 1: Classify the project as greenfield or rewrite
- Step 2: Choose minimum pipeline size (3 for greenfield, 6 for rewrite)
- Step 3: Draft prompt 001 (always spec generation)
- Step 4: Define runtime variables shared across all prompts
- Step 5: Write exit criteria + completion signal for each prompt
- Step 6: Add agent team structure and file ownership if the codebase is large
- Step 7: Add time guards and halting conditions
- Step 8: Run pipeline with iteration loop, watch for convergence
Step 1-2: Classify and size
- Greenfield (build from PRDs/specs/research docs) → 3 prompts:
001-generate-specs-from-refs.md→002-generate-plans-from-specs.md→003-generate-impl-from-plans.md - Rewrite (reverse-engineer existing code) → 6-9 prompts:
001-generate-refs-from-code.md→002-generate-specs.md→003-validate-specs.md→004-create-plans.md→005-implement.md→006-backpropagate.md
Rewrite pipelines have a feedback loop: 006 back-propagates prototype learnings into 002, which flows forward again through 004-005. This is expected, not a bug.
Step 3: Draft prompt 001
Always the spec-generation step. It reads raw material (refs or old code) and decomposes it into domain-specific spec files plus an index. Every requirement must carry a testable acceptance criterion.
Step 4: Runtime variables
Never hardcode framework/tooling specifics. Use placeholders so the same prompt file works across projects:
Markdownundefined
- Framework: {FRAMEWORK}
- Build command: {BUILD_COMMAND}
- Test command: {TEST_COMMAND}
- Lint command: {LINT_COMMAND}
- Source dir: {SRC_DIR}
- Test dir: {TEST_DIR}
### Step 5: Exit criteria + completion signal
Every prompt ends with a checklist and exactly one termination token (`<all-tasks-complete>`) the iteration loop scans for. No exceptions — a prompt without this cannot be automated in a loop.
### Step 6: Agent teams (only if needed)
If prompt 003/005 will spawn multiple agents, define:
- An ASCII tree of lead + teammates, each with an owned domain
- A file ownership table mapping every shared path to exactly one owner
- Batching rules: max 3 concurrent teammates per batch, max 3 sub-agents per teammate
- A spawn template giving each teammate full context (they inherit no history)
### Step 7: Guards
- Time guards: 10 min for mechanical tasks, 20 min for investigation tasks, 20 min category budget
- Halting conditions: no unsanctioned pushes, no out-of-ownership edits, no skipping failing tests, document blockers instead of retrying silently
### Step 8: Run and watch convergence
Start the iteration loop with 3-5 iterations. Exponentially decreasing diffs = converging. Flat or oscillating diffs = the specs are fuzzy, fix those first, not the prompts.
Example 1: Greenfield SaaS app
Input: "I have a PRD and a design doc in refs/, React + Vite, npm."
Output: 3 prompts — 001-generate-specs-from-refs.md (reads context/refs/, writes context/kits/), 002-generate-plans-from-specs.md (reads kits + impl, writes context/plans/), 003-generate-impl-from-plans.md (reads plans + kits, writes src/, tests/, context/impl/). Runtime inputs set to {FRAMEWORK}: React + Vite, {BUILD_COMMAND}: npm run build, {TEST_COMMAND}: npm test.
Example 2: Legacy PHP monolith rewrite to Rust/Tauri, evaluating two frontend frameworks
Input: "Old PHP app, need specs before rewriting in Rust, testing Svelte and React frontends in parallel."
Output: 6-prompt rewrite pipeline. 001-generate-refs-from-code.md extracts API docs/data models into shared-context/reference/ (runs once). 002-generate-specs.md writes implementation-agnostic specs to shared-context/kits/. 003-validate-specs.md produces a validation report only (no code). 004-create-plans.md and 005-implement.md run twice — once per framework repo — off the same shared specs. 006-backpropagate.md feeds prototype learnings back into 002.
Example 3: Large team, parallel domains
Input: "Auth, data, and UI domains need to be built simultaneously without merge conflicts."
Output: Prompt 003 (or 005) includes an agent team structure with a lead (delegate-only) and three teammates (domain-auth, domain-data, domain-ui), a file ownership table binding src/auth/** to domain-auth etc., and a batching rule capping concurrent teammates at 3.
- Map one prompt to exactly one Hunt phase — never combine Spec+Plan or Plan+Implement into a single prompt.
- Declare explicit input/output directories in every prompt; no implicit side effects.
- Let plan and implement prompts read/write each other's outputs (context/impl ↔ context/plans) — this bidirectional flow is the convergence mechanism, not a design flaw.
- After any source file changes, regenerate/run tests for those files to keep coverage current.
- Use
[CONDITIONAL]tasks with explicit skip conditions, and[DYNAMIC]tasks created at runtime by specific triggers (e.g., a performance gate failure). - Number prompts so lower numbers are upstream (closer to specs) and higher numbers are downstream (closer to code); reserve
000for one-time brownfield bootstrap. - When an agent hits time guards repeatedly across related tasks, treat it as a systemic signal (fuzzy spec, missing dependency) — document the pattern, don't just retry harder.
- Overloading a single prompt with multiple phases — if a prompt is trying to generate specs and implement code, split it.
- Omitting the completion signal — without
<all-tasks-complete>, iteration loops can't detect when to stop and will run forever or stop prematurely. - Hardcoding framework details instead of using
{RUNTIME_VARIABLES}, which makes the prompt non-portable. - Assigning a shared file to two teammates — always give one owner; route the other teammate's changes through the lead.
- Spawning teammates without full context — they have no inherited history; the spawn template must include specs, plans, impl tracking, and recent git log.
- Silently retrying past a time guard instead of documenting the blocker and moving to the next unblocked task.
- Treating oscillating or flat diffs as a prompt problem — it's almost always a spec clarity problem; fix the spec, not the prompt wording.