System design · 6 platforms · 9 roles (mobile) · 54 models

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.

01
Analyst
Decompose reqs
02
PM
Assign work
03
Devs
Generate code
04
Integration
Cross-file check
05
QA
Review · score
06
Feedback
Dedupe · gate
07
Summary
Final docs

score < threshold → loop back to phase 02

The Seven Phases

What each agent actually does

01

Analyst

Decomposes requirements into components with file lists and dependencies, testable & measurable acceptance criteria, technical notes, and complexity estimation.

02

Project Manager

Creates non-overlapping work assignments. Validates that no file is assigned to multiple developers. Groups related files to minimize integration churn.

03

Developers (Parallel)

Each developer receives ONLY their assigned files and can only create those files. Strictly enforced. Receives team-coordination context showing all assignments.

04

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.

05

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.

06

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.

07

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.

scoring.algorithm.md● canonical

// 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
Native SDK · streaming

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
OpenAI SDK · SSE

Google

Gemini family · 8 models

  • gemini-3-pro / gemini-3-flash
  • gemini-2.5-pro / gemini-2.5-flash
  • gemini-2.5-flash-lite
REST · server-sent

DeepSeek

Reasoning · 2 models

  • deepseek-reasoner
  • deepseek-chat
OpenAI-compatible API

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/

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.

web-architecture.txt● single process
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