System Overview
Ralphmania is a spec-driven AI orchestrator built on hexagonal architecture. The user writes a specification.md and a validation script; the orchestrator drives one or more AI agents in parallel to implement every scenario, validating after each round.
Orchestrator Workflow
The orchestrator is a finite state machine (FSM) defined in src/machines/state-machine.ts. Each state transition is logged and checkpointed to .ralph/loop-state.json for crash recovery.
State persistence: A checkpoint is written after every state transition. If the process crashes, the orchestrator resumes from the last checkpointed state and iteration count.
Worker Pipeline
Each worker runs in an isolated git worktree and follows its own FSM defined in src/machines/worker-machine.ts. The parent orchestrator prescribes exactly one scenario per worker to prevent conflicts.
Non-interactive: All agent subprocesses run with CI=true, no TTY, and stdin null to prevent hangs in automated pipelines.
Merge & Reconcile
Workers enqueue their worktree branches into a merge queue as they finish. The orchestrator dequeues and merges sequentially. On conflict, a reconciliation agent is spawned to resolve it — no work is ever discarded.
Model Escalation
The Claude agent uses a 2-level escalation ladder controlled per scenario in .ralph/escalation.json. Escalation increases monotonically during rework and resets when the scenario exits NEEDS_REWORK.
| Level | Model | Tier | Trigger |
|---|---|---|---|
| L0 | Sonnet | general / high effort | Default for new scenarios |
| L1 | Opus | strong / high effort | Scenario marked NEEDS_REWORK |
For Codex agents, a rework-count threshold determines whether the general or strong model is used.
Scenario Lifecycle
Every scenario in progress.md follows a strict state machine defined in src/machines/scenario-machine.ts. Invalid transitions are rejected and logged.
From NEEDS_REWORK, the scenario cycles back to WIP for another attempt. Any non-terminal scenario can be marked OBSOLETE (terminal) by the user. The orchestrator skips OBSOLETE scenarios in completeness checks.
Plugin Lifecycle
Plugins intercept seven hooks during the orchestrator and worker lifecycles. Each hook is annotated in the diagrams above where it fires.
Mutability: Hooks that return a value can override the orchestrator's decision. For example, onPromptBuilt can rewrite the prompt and onValidationComplete can flip a failure to a pass.
File Map
Source is organized following hexagonal architecture: pure domain logic in src/machines/, I/O adapters in src/ports/, and domain-specific code clustered in subdirectories.
| Directory | Responsibility |
|---|---|
src/machines/ | FSMs: orchestrator, worker, scenario state machines (pure logic, no I/O) |
src/ports/ | Port contracts (types.ts) and Deno adapters (impl.ts) |
src/orchestrator/ | Parallel loop, merge queue, conflict-aware clustering |
src/git/ | Worktree creation, cleanup, merge operations |
src/parsers/ | Progress row parsing, scenario ID extraction |
src/gui/ | Live GUI: SSE server, islands, event bus, publish pipeline |
site/ | Static docs site: Preact pages, CSS, build script |
.ralph/ | Runtime state: escalation, checkpoints, validation logs, receipts, worktrees |
Key data flow
specification.md --> prompt --> agent --> code changes --> git commit
|
progress.md <---------- agent updates status -------------+
|
specification.validate.sh <--- runs after merge ----------+
|
+--> .ralph/validation/iteration-N.log --> feeds next iteration