How the
orchestrator works.
A 7-phase software development pipeline (9 roles on Mobile) with multi-provider support, quality-gated iterations, per-provider cost tracking, and equivalent concurrency models across six feature-parity implementations.
Pipeline Flow
Requirements in. Working app out.
Each box is a separate agent role. Phases 3 and 5 run in parallel. If the score doesn't clear the threshold, the pipeline loops back to Developers with the deduplicated QA feedback.
score < threshold → loop back to phase 02
The Seven Phases
What each agent actually does
Analyst
Decomposes requirements into components with file lists and dependencies, testable & measurable acceptance criteria, technical notes, and complexity estimation.
Project Manager
Creates non-overlapping work assignments. Validates that no file is assigned to multiple developers. Groups related files to minimize integration churn.
Developers (Parallel)
Each developer receives ONLY their assigned files and can only create those files. Strictly enforced. Receives team-coordination context showing all assignments.
Integration Architect
Static analysis verifies cross-file consistency: CSS classes used in HTML exist, HTML IDs referenced in JS exist, JS element selectors match HTML structure, module imports resolve.
QA Review (Parallel)
Each QA agent independently reviews ALL files, not just a subset. Checks critical integration points. Marks severity: critical, major, minor. Optional browser-driven testing.
Feedback Coordinator
Deduplicates similar issues across QA agents. Calculates completion score using the weighted algorithm (or geometric-mean scorecard on mobile). Decides iterate vs. done.
Summary Generator
Generates user-facing documentation including the QA issue list by severity, acceptance criteria pass/fail, score breakdown, and how-to-run instructions.
Scoring Algorithm
Weighted average · with capping
The CLI / Web ports use this weighted-average scoring with score caps for severe issues. The Mobile variant adopts a five-dimension geometric-mean scorecard instead.
// v1 scoring model · arithmetic weighting + per-severity score caps
// (caps patch a structural limitation: weighted averages let critical
// issues hide behind high AC + minor scores · see Mobile's
// Quality Scorecard for the geometric-mean approach)
// Weighted completion score calculation
finalScore = (criticalScore × 0.50) +
(majorScore × 0.20) +
(minorScore × 0.10) +
(acScore × 0.20)
// Issue penalties per occurrence
criticalScore = max(0, 1.0 - critical × 1.00)
majorScore = max(0, 1.0 - major × 0.25)
minorScore = max(0, 1.0 - minor × 0.10)
acScore = passed / total
// Score capping (prevents inflated scores)
if critical ≥ 1 ⇒ max = max(0.3, 0.6 - n × 0.15)
if major ≥ 3 ⇒ max = max(0.4, 0.75 - (n - 2) × 0.1)
Provider Layer
Four providers, one interface
Each provider implements a common base class with createMessage(). Streaming, tool use, multimodal content, and cost calculation all flow through the same shape.
Anthropic
Claude family · 9 models
- claude-opus-4-7
- claude-sonnet-4-6
- claude-haiku-4-5-20251001
OpenAI
GPT family · 35 models
- gpt-5.2-codex
- gpt-5 / gpt-5-mini / gpt-5-nano
- gpt-4.1 / gpt-4o / gpt-4o-mini
Gemini family · 8 models
- gemini-3-pro / gemini-3-flash
- gemini-2.5-pro / gemini-2.5-flash
- gemini-2.5-flash-lite
DeepSeek
Reasoning · 2 models
- deepseek-reasoner
- deepseek-chat
Concurrency Models
Six runtimes. Same shape.
Every implementation enforces the same concurrency contract: parallel agents bounded by a configurable max, with a join point before the next phase.
Node.js
Event Loop- →Promise.all for parallelism
- →Promise.race for semaphore slots
- →Executing array tracks active
Python
asyncio- →asyncio.Semaphore(n)
- →asyncio.gather
- →async with for clean acquire
Go
Goroutines- →Channel-based semaphore
- →sync.WaitGroup for join
- →chromedp for browser automation
.NET
async/await- →SemaphoreSlim for limits
- →Task.WhenAll for parallelism
- →Native HttpClient API
Next.js
SSE + EventEmitter- →Wraps Node.js orchestrator
- →SSE stream to browser
- →useReducer state machine
Mobile
Kotlin Coroutines- →coroutineScope { async }.awaitAll()
- →StateFlow<RunState> reducer
- →Foreground service + Doze-safe
Project Structure
One monorepo. Six entry points.
rdn-swarm/
src/
nodejs/
sdlc-orchestrator.js # ~4,040 LOC, canonical reference
providers/ # anthropic · openai · google · deepseek
python/
sdlc/orchestrator.py # ~3,000 LOC · asyncio
sdlc/providers/
go/
sdlc/orchestrator.go # ~3,590 LOC · goroutines
providers/
dotnet/
Swarm/SdlcOrchestrator.cs # ~3,030 LOC · Task.WhenAll
Swarm/Providers/
web/
lib/web-orchestrator.ts # SDLCOrchestrator subclass + SSE
lib/orchestrator/ # copied from nodejs/ as JS
src/app/ # Next.js pages + API routes
src/hooks/useRunEvents.ts # SSE consumer + useReducer
# Companion repo, native Android client
rdn-swarm-mobile-droid/
app/src/main/java/net/reidell/swarm/mobile/
data/orchestrator/SdlcOrchestratorImpl.kt # ~2,250 LOC · full 9-role port
data/orchestrator/qa/ # WebView capture + click probe
data/llm/ # 4 streaming providers
data/settings/ApiKeyVault.kt # EncryptedSharedPreferences
data/run/ # Room event log + RunState reducer
ui/screens/ # 8 screens (home · newrun · run · data · ...)
service/SwarmRunService.kt # foreground service for long runs
Web Frontend
A subclass that emits events.
The Next.js port is the canonical orchestrator code copied directly from src/nodejs/ and imported as-is. A WebOrchestrator subclass overrides each phase method to emit typed SSE events before/after calling super.
A useReducer hook on the browser side accumulates events into a full RunState. Every event is also appended to disk, so mid-run reconnects replay seamlessly and completed runs can be browsed and re-played through the same dashboard UI.
Browser <--SSE--> Next.js Server (port 3000)
├── Auth (OIDC · Rdn.Identity)
├── RunManager (singleton)
│ ├── WebOrchestrator (extends SDLCOrchestrator)
│ │ ├── EventEmitter → SSE stream
│ │ ├── Promise-based userCheckIn
│ │ └── Console capture → SSE events
│ ├── RunArchive (event sourcing → fs)
│ └── Event broadcast → SSE subscribers
├── Providers (anthropic · openai · google · deepseek)
└── Static output serving (/output/*)Mobile Architecture
The same orchestrator, no server in the loop.
The Android client runs the same 7-phase pipeline plus two additional roles (Visual QA + Test Author) entirely on-device, with user-supplied keys in a hardware-backed Keystore. Reducer-driven UI, Room-persisted event archive, and a foreground service that survives Doze and low-memory backgrounding.
Tour the Mobile App→