Engineering Reference · orchestrator/loopdriver

loopdriver — The Dark Forge Loop

The Dark Forge (DFG) loop is an 8-phase agentic cycle that drives autonomous task execution. Phases 1–5 are implemented. Phases 0, 6, and 7 are defined but not called. This page covers every phase, the gap between the spec and the implementation, and how the loop connects to Zeus.

The 8-phase cycle

flowchart LR P0["Phase 0\nRecovery\n⚠ not called"] P1["Phase 1\nPreflight"] P2["Phase 2\nPlanning"] P3["Phase 3\nDispatch"] P4["Phase 4\nCollect"] P5["Phase 5\nMerge"] P6["Phase 6\nBuild\n⚠ not called"] P7["Phase 7\nDeploy\n⚠ not called"] P0 -.->|crash resume only| P1 P1 --> P2 P2 --> P3 P3 --> P4 P4 -->|more issues| P3 P4 --> P5 P5 -->|next cycle| P1 P5 -.->|planned| P6 P6 -.->|planned| P7 P7 -.->|next cycle| P1 style P0 fill:#3a2020,color:#BF616A,stroke:#BF616A style P6 fill:#3a2020,color:#BF616A,stroke:#BF616A style P7 fill:#3a2020,color:#BF616A,stroke:#BF616A style P1 fill:#1a2535,color:#88C0D0,stroke:#88C0D0 style P2 fill:#1a2535,color:#88C0D0,stroke:#88C0D0 style P3 fill:#1a2535,color:#88C0D0,stroke:#88C0D0 style P4 fill:#1a2535,color:#88C0D0,stroke:#88C0D0 style P5 fill:#1a2535,color:#88C0D0,stroke:#88C0D0
PhaseNameStatusPurpose
0RecoveryConstant only — not calledResume interrupted session from checkpoint
1PreflightImplemented (minimal)Validate environment, triage issue backlog
2PlanningImplemented (minimal)Generate implementation plan per issue
3DispatchImplemented (minimal)Assign issues to coder agents, launch work
4CollectImplemented (minimal)Gather coder outputs, review results
5MergeImplemented (minimal)Synthesise final response, PR creation
6BuildConstant only — not calledCode synthesis, lint gating, test runner integration
7DeployConstant only — not calledGit push, PR creation, branch protection handling

Driver.Run — single cycle

Driver.Run(ctx) executes one cycle (phases 1–5) and returns a CycleResult with phase outcomes, issues processed, and a terminal action: "continue", "done", "human_review", or "error".

Driver.RunAutonomous(ctx) wraps Run() in a loop, draining the issue backlog until exhausted, human_review is triggered, or MaxCycles is reached.

Dispatch strategy is configurable: "interleaved" (default) plans issue 1 then immediately dispatches it, then plans issue 2 and dispatches it. "batch" plans all issues first, then dispatches all. Interleaved is canonical and reduces time-to-first-work.

// DriverConfig
type DriverConfig struct {
    MaxCycles          int    // 0 = unlimited
    DispatchStrategy   string // "interleaved" (default) or "batch"
    HumanApprovesPlans bool   // pause at Phase 2 for human review
    Autonomous         bool   // run continuously vs. single cycle
    PMMode             bool   // enable tech-lead delegation validation
}

How loopdriver calls Zeus

loopdriver communicates with Zeus through the LLMInvoker interface. In the shell, a thin zeusLLMInvoker struct wraps Zeus.Generate() to satisfy the interface without creating a circular import.

classDiagram class LLMInvoker { <<interface>> +Invoke(ctx, prompt, workDir) map } class zeusLLMInvoker { z Zeus +Invoke(ctx, prompt, workDir) map } class CLILLMInvoker { binary string +Invoke(ctx, prompt, workDir) map } class Driver { +Run(ctx) CycleResult +RunAutonomous(ctx) Metrics } LLMInvoker <|.. zeusLLMInvoker LLMInvoker <|.. CLILLMInvoker Driver --> LLMInvoker : invokes per phase

CLILLMInvoker spawns a subprocess (intended for the original dfg binary design). With the decision that dfg is not a separate binary — all DFG functionality lives inside olympusCLILLMInvoker is a dead code path. zeusLLMInvoker is the only path that matters.

What the loop actually sends to Zeus

Each phase builds a prompt string via buildPhasePrompt(phase, issues) and calls invoker.Invoke(ctx, prompt, workDir). Phase 2 now uses the internal/orchestrator/planning package to produce validated structured JSON plans.

PhasePrompt sourceOutput
Preflight buildPhasePrompt(PhasePreFlight, issues) JSON with issues_selected
Planning Batch: planning.BuildBatchPlanPrompt(issues)
Interleaved: planning.BuildPlanPrompt(issue, intentHint)
Structured Plan JSON validated by planning.Validate(); written to .olympus/plans/<session>-<issue>.json
Dispatch Built from plan.Steps JSON (typed struct, not free text) Coder agent invocation
CollectbuildPhasePrompt(PhaseCollect, issues)Results JSON
MergebuildPhasePrompt(PhaseMerge, issues)Final summary

Aegis-3: Circuit Breaker

The loop now includes a per-task circuit breaker (internal/orchestrator/circuitbreaker). After two consecutive failures on the same work unit, the circuit trips and surfaces an interactive prompt to the operator:

⚡ Circuit open: this task has stalled 2 times with the same error.
Error: <last error>
[h] pause for human review   [r] retry with a different approach   [a] abort
  • [h] Human review — saves circuit state to .olympus/circuit/, writes a checkpoint (Mnemosyne), returns ErrHumanReviewRequired. Restart Olympus after addressing the underlying issue to resume from the checkpoint.
  • [r] Retry — resets the circuit and re-runs the phase with the prior error prepended as context.
  • [a] Abort — skips this work unit and continues to the next issue.

In non-interactive (CI) environments, the prompt defaults to [h] automatically.

Recovery — spec vs. reality

The Phase 0 spec (embedded in the binary as prompts/startup-phases/phase-0-recovery.md) describes:

  • Read a structured JSON checkpoint from ~/.olympus/checkpoints/
  • Validate git state: clean working tree, correct branch, no merge conflicts
  • Resume from the exact phase that was active at crash time (enforced by StateMachine's recovery target)
  • Emit a structured RECOVERY_REPORT JSON before continuing

Reality: The PhaseRecovery = 0 constant is defined. Driver.Run() starts at Phase 1 unconditionally. The checkpoint package (internal/checkpoint) exists and maybeCheckpoint() fires at 80% context threshold, but it saves a plain text snapshot — not a structured resume point. The StateMachine's SetRecoveryTarget() method exists but is never called.

Build and Deploy — not yet implemented

The spec describes Phase 6 (Build) as a code synthesis phase: diff generation, test runner integration, lint gating, Hephaestus-backed patch application. Phase 7 (Deploy) handles git push, PR creation with branch protection awareness, and release tagging.

Both phases are defined as integer constants. Neither is called anywhere in Driver.Run(). The validTransitions map in StateMachine includes the transitions 5→6 and 6→7 already, ready for when the phases are implemented.

Note: Phase 7 Deploy currently means olympus deploys — git push, PR creation, not deploying user applications. The naming follows the DFG spec, not infrastructure deployment.

How users invoke the loop

The Dark Forge loop is not a separate binary. There is no dfg executable. All loop functionality is embedded in the olympus binary under the olympus orchestrate subcommand path:

# Single cycle on a task
olympus orchestrate run --task "implement issue #42"

# Drain the full issue backlog autonomously
olympus orchestrate run --autonomous

# Governance and environment checks (Phase 1 preflight)
olympus govern verify

# Resume from last checkpoint
olympus orchestrate resume

These commands do not yet exist — they are the target state. Today, the loop is invoked programmatically via loopdriver.NewDriver(...).Run(ctx) or through the /startup slash command in the TUI shell.