Skip to content

Idea to production pipeline

The complete lifecycle of work in protoLabs Studio, from initial signal through merged PR. This document is the canonical reference for all pipeline phases, gates, authority agents, and state transitions.

Overview

Every piece of work flows through an 8-phase pipeline with two human gates. The pipeline has two branches (ops and gtm), three authority agents, a Lead Engineer state machine, and fast-path supervisor rules.

Signal → TRIAGE → RESEARCH → SPEC → SPEC_REVIEW → DESIGN → PLAN → EXECUTE → PUBLISH
                                         ^ GATE                               ^ GATE

GTM branch skips DESIGN and PLAN (content doesn't need architectural decomposition).

Signal entry

Work enters through four channels, all routed by SignalIntakeService:

SourceClassificationPath
GitHub issue/PR eventopsLead Engineer state machine
Discord eventops / gtmSignal classification + route
MCP create_featureops (fast path)Direct to board, skip PM
MCP process_ideaops (full path)PM Agent research + PRD

GTM gate: The entire GTM branch is controlled by the gtmEnabled global setting (default: false). When disabled, SignalIntakeService forces all signals to ops, content API routes return 403, and the UI hides GTM-related nodes. Enable via settings to activate GTM routing.

Fast path skips the PM pipeline -- feature goes straight to the board and Lead Engineer picks it up. Use when you know exactly what needs building.

Full path routes through PM Agent for research, PRD generation, and CTO approval before decomposition.

Signal intent classification

SignalIntakeService applies a second classification layer -- intent -- independent of the ops/gtm routing. Intent identifies the nature of the signal so the Lead Engineer and downstream agents can handle it appropriately without re-classifying.

Type: SignalIntent in libs/types/src/signal-intent.ts

IntentDescriptionRouting
work_orderConcrete task ready for implementation (MCP create_feature, UI board action)Ops pipeline -- normal execution
ideaVague concept needing PM refinement (MCP process_idea, Discord brainstorm channels)PM Agent research + PRD
feedbackCommentary on existing work (PR review, Discord discussion)Routes to running agent via sendMessageToAgent() or followUpFeature()
conversationalCasual message or question -- no work item created (Discord @mentions, social exchanges)GTM or acknowledged without feature creation
interruptUrgent signal requiring immediate human attention (SLA breach, emergency)Bypasses PM pipeline entirely -- creates HITL form directly

The intent field is threaded onto all signal:routed events. The interrupt fast-path uses HITLFormService (wired via setHITLFormService() at server startup).

The 8 phases

Defined in libs/types/src/pipeline-phase.ts.

Phase 1: TRIAGE

Gate: auto | Agent: SignalIntakeService | workItemState: idea

Classify the signal as ops or gtm. Create the feature. Emit authority:idea-injected.

Phase 1.5: TRIAGE + CLARIFICATION (optional HITL gate)

Gate: auto or HITL | Agent: PM Agent (Opus triage) | workItemState: research

During triage, the PM Agent evaluates whether the idea is too vague to produce a quality PRD. If clarification is needed, a HITL form dialog is shown to the user with 2-4 targeted questions (generated in the same triage LLM call at zero extra cost). The pipeline pauses up to 10 minutes for a response. On timeout or cancellation, it proceeds gracefully with the original idea. User answers are appended to the feature description as ## User Clarifications before research begins.

Phase 2: RESEARCH

Gate: auto | Agent: PM Agent (Sonnet) | workItemState: research

PM Agent reads the codebase with read-only tools (enriched by any HITL clarification answers). Investigates feasibility, existing patterns, and constraints. Emits authority:pm-research-completed.

Phase 3: SPEC

Gate: auto | Agent: PM Agent (Sonnet) | workItemState: pm_processing

PM Agent generates a SPARC PRD (Situation, Problem, Approach, Results, Constraints). Emits authority:pm-prd-ready.

Phase 4: SPEC_REVIEW

Gate: review (ops) / manual (gtm) | Agent: none (human) | workItemState: prd_ready

First human gate. The pipeline holds here (awaitingGate: true). CTO reviews the PRD and approves or requests changes. On approval, emits authority:pm-review-approved and transitions to approved.

The PRD approval endpoint (/api/engine/signal/approve-prd) bridges directly to pipelineOrchestrator.resolveGate(), so approving the PRD also advances the pipeline gate in a single action. Rejecting the PRD resets the feature to idea state and rejects the gate.

If a HITL form is pending for the feature (e.g., clarification questions), clicking the gated node in the flow graph or the amber gate indicator in the progress bar opens the HITL form dialog directly.

Phase 5: DESIGN (ops only)

Gate: auto | Agent: ProjM Agent | workItemState: approved

ProjM creates a project with milestones. Only one milestone can be in-progress at a time (sequential execution). Emits milestone:planned.

GTM branch skips this phase entirely.

Phase 6: PLAN (ops only)

Gate: auto | Agent: ProjM Agent | workItemState: planned

ProjM decomposes milestone phases into child features with dependencies. Sets up the execution order. Emits milestone:started. Features transition to ready.

GTM branch skips this phase entirely.

Phase 7: EXECUTE

Gate: auto | Agent: Lead Engineer + persona agents | workItemState: in_progress

The Lead Engineer state machine takes over. See the Lead Engineer section below for the full sub-state machine (INTAKE, PLAN, EXECUTE, REVIEW, MERGE, DEPLOY, DONE).

Phase 8: PUBLISH

Gate: review (ops) / manual (gtm) | Agent: PR feedback service | workItemState: done

Second human gate. PR is created, CI runs, CodeRabbit reviews. The pipeline can hold here for human review if issues are found. On clean pass, auto-proceeds. PR merges to target branch (dev, epic, or main). Board status updates to done. Emits feature:pr-merged.

Gate system

Defined in pipeline-orchestrator.ts.

Three gate modes control phase transitions:

ModeBehavior
autoProceed immediately on phase completion
reviewAuto-proceed if clean; hold if issues found
manualAlways hold, wait for human action

Default gate configuration (ops)

Phase transitionGate
TRIAGE → RESEARCHauto
RESEARCH → SPECauto
SPEC → SPEC_REVIEWauto
SPEC_REVIEW → DESIGNreview
DESIGN → PLANauto
PLAN → EXECUTEauto
EXECUTE → PUBLISHreview
PUBLISH → doneauto

Gate hold state

When a gate holds, the feature's pipelineState records:

typescript
{
  awaitingGate: true,
  awaitingGatePhase: 'SPEC_REVIEW',
  gateArtifacts: { /* phase-specific context */ }
}

Gate resolution emits pipeline:gate-resolved and advances to the next phase.

Duplicate event guard: Multiple events can map to the same phase completion (e.g., both authority:pm-prd-ready and ideation:prd-generated map to SPEC completed). The orchestrator's handlePhaseEvent checks !pipelineState.awaitingGate before calling advancePhase, preventing duplicate gate holds from redundant events.

Authority agents

Three AI agents manage the pre-execution pipeline. Defined in apps/server/src/services/authority-agents/.

PM Agent (pm-agent.ts)

Phases: TRIAGE, RESEARCH, SPEC

  • Triggered by authority:idea-injected
  • Opus triage decides web research need + generates clarifying questions for vague ideas
  • If clarification needed, shows HITL form dialog (10 min TTL, callerType: 'api')
  • Researches codebase with read-only tools (Sonnet), enriched by user clarification
  • Generates SPARC PRD
  • Posts to Discord for CTO review
  • State flow: idea → pm_review → research → [HITL form] → pm_processing → prd_ready

ProjM Agent (projm-agent.ts)

Phases: DESIGN, PLAN

  • Triggered by authority:pm-review-approved
  • Creates project with milestones (sequential, one at a time)
  • Decomposes phases into child features with dependencies
  • State flow: approved → planned → ready

EM Agent (em-agent.ts)

Phase: EXECUTE kickoff

  • Polls for ready features every 10 seconds
  • Checks capacity (WIP limit, default 3)
  • Assigns model by complexity, triggers auto-mode
  • State flow: ready → in_progress

Lead Engineer state machine

Defined in apps/server/src/services/lead-engineer-service.ts. This is the per-feature execution engine that runs inside phase 7 (EXECUTE).

INTAKE → PLAN → EXECUTE → REVIEW → MERGE → DEPLOY → DONE
                    |         |
                 (retry)   (changes requested → back to EXECUTE)
                    |
                 ESCALATE (blocked, needs intervention)

INTAKE

Check dependencies, assign persona agent based on feature domain detection:

Domain keywordsAgent
test, qaqa-engineer
docs, documentationdocs-engineer
ui, frontend, componentfrontend-engineer
api, backend, servicebackend-engineer
deploy, ci, infrastructuredevops-engineer
architectural complexityengineering-manager
Mixed or unclearbackend-engineer

Model selection by complexity: small → Haiku, medium/large → Sonnet, architectural → Opus. Features with 2+ prior failures auto-escalate to Opus. User-configured agentExecutionModel in workflow settings takes priority over complexity-based defaults.

If dependencies unmet → ESCALATE. If plan needed (large/architectural or 3+ files) → PLAN. Otherwise → EXECUTE.

PLAN (complex features only)

Generate implementation plan via LLM. The processor also attempts to generate a StructuredPlan with machine-parseable goal, tasks, acceptance criteria, and deviation rules. For large/architectural features, an antagonistic review gate challenges the plan before execution (configurable via pipeline.antagonisticPlanReview). Up to 2 plan retries before escalation.

EXECUTE

Persona agent runs in isolated worktree. On success → REVIEW. On failure: retry with context (max 3 agent retries + 3 infra retries tracked separately). Infrastructure failures (git push, lock files) do not consume the agent retry budget. After exhausting retries → ESCALATE.

REVIEW

PR created, CI runs, CodeRabbit reviews. ReviewProcessor polls PR state every 30 seconds via PRFeedbackService (fallback: gh CLI):

  • On changes_requested: collect review feedback, loop back to EXECUTE (max 4 remediation cycles, max 2 PR iterations)
  • On approved + CI passing → MERGE
  • On pending >45 minutes → ESCALATE with diagnostic
  • External merge detection: if the branch has a merged PR on GitHub, transition directly to DONE

MERGE

Merge PR via gh pr merge. Strategy: promotion PRs (targeting staging/main) always use --merge; feature PRs use prMergeStrategy from global settings (default: squash). Retries with 60-second delay on failure. On success → DEPLOY.

DEPLOY

Post-merge verification and learnings capture:

  1. Run npm run typecheck (+ build:packages if libs/ touched) with 120s timeout per command
  2. On verification failure, create a bug-fix feature on the board
  3. Generate reflection via haiku LLM call (fire-and-forget)
  4. Run goal verification against structured plan acceptance criteria (fire-and-forget, advisory)
  5. Emit feature:completed

DONE

Terminal state. Cleanup checkpoint, index engineering learnings via KnowledgeStoreService.

Escalation routing

When the Lead Engineer can't resolve a situation, signals are routed through the EscalationRouter to appropriate channels based on severity and signal type. See Escalation routing for the full architecture.

TriggerAction
Feature fails 3+ timesEscalate model, then flag Ava
PR fails CI 3+ timesFlag Ava with failure context
Budget exceededStop agent, flag Ava
Circular dependencyFlag Ava
Unknown errorFlag Ava for manual triage

Fast-path supervisor rules

Defined in apps/server/src/services/lead-engineer-rules.ts. 16 pure functions (no LLM) that react to events. Key rules:

RuleTriggerAction
mergedNotDonePR merged, status still reviewMove to done
orphanedInProgressIn-progress >4h, no agentReset to backlog (block if 3+ failures)
staleDepsBlocked + all deps doneUnblock
autoModeHealthBacklog >0 + auto-mode offRestart auto-mode
staleReviewReview >30min, no auto-mergeEnable auto-merge
stuckAgentAgent running >2hAbort and resume with wrap-up prompt
prApprovedPR approvedEnable auto-merge, resolve threads
capacityRestartFeature completed + more backlogRestart auto-mode
projectCompletingAll features doneTrigger project completion
classifiedRecoveryEscalation with retryable errorAuto-retry if confidence >=0.7
hitlFormResponseHITL form submittedRetry / provide context / skip / close
reviewQueueSaturatedReview count >= max (5)Log warning, scheduler pauses pickup
errorBudgetExhaustedBudget exhaustedLog warning, restrict to bug-fix features

Feature status system

Five canonical statuses on the board (libs/types/src/feature.ts):

backlog → in_progress → review → done
             |           |
          blocked < < < -+

Pipeline phase to status mapping

Pipeline phaseworkItemStateBoard status
TRIAGEideabacklog
RESEARCHresearchbacklog
SPECpm_processingbacklog
SPEC_REVIEWprd_readybacklog
DESIGNapprovedbacklog
PLANplannedbacklog
EXECUTEin_progressin_progress
PUBLISHdonedone

Dependency resolution

Defined in libs/dependency-resolver/src/resolver.ts. Uses Kahn's algorithm with priority-aware selection.

Foundation dependencies (isFoundation: true) require the dependency to be done (merged to main).

Standard dependencies allow review or done -- work can start once the dependency has a PR up.

Observability

Every pipeline run creates a Langfuse trace (UUID). Each phase creates a span within the trace. Stored in pipelineState.traceId and pipelineState.phaseSpanIds.

Multi-pipeline UI

The flow graph view tracks all concurrent pipelines, not just one. When multiple features have active pipeline states, a pill selector appears above the progress bar.

Components:

  • PipelinePillSelector -- horizontal row of chips, each showing feature title + status dot (violet=active, amber=gated, emerald=done). Auto-hides when <=1 pipeline active.
  • PipelineProgressBar -- unchanged, always shows the selected pipeline's 8-phase stepper.
  • usePipelineProgress hook -- tracks a Map<featureId, PipelineEntry> internally. WebSocket events upsert by featureId. Exposes pipelines array + selectedFeatureId + setSelectedFeatureId.

Gate interaction: Clicking the amber gate indicator on the progress bar or a gated pipeline-stage node opens the pending HITL form for the selected pipeline's feature (if one exists). The Advance/Reject buttons in the progress bar resolve the selected pipeline's gate.

Key files

FilePurpose
libs/types/src/pipeline-phase.ts8 phases, gate modes, transitions
libs/types/src/feature.tsFeature status, pipelineState
libs/types/src/authority.tsWorkItemState (15 states)
libs/types/src/lead-engineer.tsLead Engineer types
apps/server/src/services/pipeline-orchestrator.tsPhase transitions and gates
apps/server/src/services/signal-intake-service.tsSignal classification
apps/server/src/services/lead-engineer-service.tsState machine
apps/server/src/services/lead-engineer-rules.tsFast-path rules
apps/server/src/services/auto-mode-service.tsOrchestration, worktree mgmt
apps/server/src/services/feature-scheduler.tsScheduling loop, dep resolution
apps/server/src/services/notification-router.tsNotification signal routing
apps/server/src/services/pr-feedback-service.tsPR polling and remediation
apps/server/src/services/hitl-form-service.tsHITL form creation and responses
apps/server/src/services/escalation-router.tsEscalation signal routing
apps/server/src/services/authority-agents/pm-agent.tsPM (research + PRD + HITL)
apps/server/src/services/authority-agents/projm-agent.tsProjM (milestone planning)
apps/server/src/services/authority-agents/em-agent.tsEM (capacity + execution)
apps/ui/src/components/views/flow-graph/hooks/use-pipeline-progress.tsMulti-pipeline tracking hook
apps/ui/src/components/views/flow-graph/pipeline-pill-selector.tsxPipeline selector UI
apps/ui/src/components/views/flow-graph/pipeline-progress-bar.tsxPhase stepper + gate button
apps/ui/src/components/shared/hitl-form/hitl-form-dialog.tsxHITL form dialog

Next steps

Built by protoLabs — Open source on GitHub