How the no-mistakes Daemon Manages Runs and Its Lifecycle

The no-mistakes daemon orchestrates pipeline execution through a centralized RunManager that tracks active runs in thread-safe maps, serializes per-repo/branch operations via mutex locks, and guarantees cleanup through deferred work-tree removal and database state updates.

The run lifecycle in the kunchenguid/no-mistakes repository is managed by a singleton RunManager instantiated at daemon startup. This architecture ensures that every push triggers exactly one pipeline execution while providing clear guarantees for cancellation, crash recovery, and resource cleanup.

Core Run Lifecycle Architecture

The RunManager Singleton

At daemon startup, RunWithOptions in internal/daemon/daemon.go (line 37) creates a single RunManager instance that lives for the entire process lifetime. This manager acts as the central authority for all run state, coordinating between incoming hooks, active executions, and client subscriptions.

Thread-Safe Run Tracking

The RunManager in internal/daemon/manager.go protects run state with three synchronized maps (lines 30-36):

  • executors: Maps runID to pipeline.Executor instances
  • cancels: Maps runID to context.CancelCauseFunc for cancellation signaling
  • dones: Maps runID to a channel that closes when the run’s goroutine finishes

A sync.RWMutex guards these maps to prevent race conditions during concurrent operations.

Per-Repo/Branch Serialization

To prevent duplicate pipelines from concurrent pushes, the manager uses a sync.Map called branchLocks (lines 41-48). Each key stores a *sync.Mutex keyed by repoID/branch. Before starting any run, startRun acquires this mutex, ensuring that only one run per branch executes at a time.

Starting and Executing Runs

Handling Push Events

When a git push arrives, the daemon routes it through HandlePushReceived (lines 81-95 in manager.go). This method validates the push, extracts the repository ID and branch, then delegates to startRun (lines 55-120).

The startRun function performs the following sequence:

  1. Creates a database row to persist run metadata
  2. Materializes a temporary work-tree using git.WorktreeAdd
  3. Loads global and repository-specific configuration
  4. Resolves the trusted default-branch SHA for secure baseline comparisons
  5. Builds the pipeline agent and launches execution in a background goroutine

Background Execution Model

The background goroutine registers itself in the executors map and broadcasts progress events via m.broadcast. A deferred block (starting at line 44) ensures cleanup executes even if the pipeline panics:

// Simplified execution flow from internal/daemon/manager.go
defer func() {
    // Signal completion
    close(done)
    // Remove work-tree from disk
    git.WorktreeRemove(worktreePath)
    // Clean up bookkeeping maps
    delete(m.executors, runID)
    delete(m.cancels, runID)
    delete(m.dones, runID)
    // Record telemetry
    m.recordTelemetry(runID)
}()

Cancellation and Superseding

Graceful Shutdown Handling

The Shutdown method (lines 64-80) implements graceful termination. It sets an atomic shuttingDown flag, copies all active cancel functions from the cancels map, and invokes each with a "daemon shutting down" error cause. The method then waits up to 30 seconds for all done channels to close, allowing in-flight runs to complete cleanup before the process exits.

Individual runs can be aborted via HandleCancel (lines 92-100), which looks up the specific run’s cancel function and invokes it with RunCancelReasonAbortedByUser.

Superseding Stale Runs

When a new push arrives for a branch that already has active runs, cancelActiveRuns (lines 120-152) enumerates matching executions, cancels them with RunCancelReasonSuperseded, and waits for their done channels (with a 30-second timeout) before allowing the new run to start. This prevents resource contention and ensures only the latest commit is being built.

Event Subscription and Observability

Clients can subscribe to live run events through the Subscribe method (lines 66-79). This creates a buffered channel, stores it in the subscribers map, and returns an unsubscribe closure. When a run completes, closeSubscribers closes all channels and marks the run as completed to prevent new subscriptions to finished runs.

// Subscribe to live events from CLI/UI
ch, unsub := mgr.Subscribe(runID)
for ev := range ch {
    fmt.Printf("event %s: %s\n", ev.Type, ev.Message)
}
unsub()

Crash Recovery and Cleanup

On startup, daemon.go invokes recoverOnStartup (lines 45-70) to restore consistent state after a crash. This function:

  1. Reaps orphaned server processes from previous daemon instances
  2. Migrates legacy gate hooks to current format
  3. Calls db.RecoverStaleRuns to mark any runs left in non-terminal states as failed
  4. Walks the work-tree directory and removes stray directories left behind by interrupted executions

This ensures the system starts with a clean slate, preventing "ghost" runs from consuming resources or blocking new executions.

Summary

  • Centralized management: A single RunManager singleton in internal/daemon/manager.go coordinates all run lifecycle operations.
  • Safe concurrency: Three protected maps (executors, cancels, dones) and per-branch mutexes prevent races and duplicate pipelines.
  • Resource guarantees: Deferred cleanup in background goroutines ensures work-trees are removed and database state is updated even during panics.
  • Cancellation strategies: Runs can be cancelled via user request, superseded by newer pushes, or gracefully terminated during daemon shutdown with a 30-second timeout.
  • Crash resilience: recoverOnStartup in internal/daemon/daemon.go reconciles database state with filesystem reality after unexpected restarts.

Frequently Asked Questions

How does the no-mistakes daemon prevent duplicate pipeline runs for the same branch?

The daemon uses a sync.Map called branchLocks that stores a *sync.Mutex for each repoID/branch combination. Before starting a run, startRun acquires this mutex, ensuring that concurrent pushes to the same branch are serialized and only one run executes at a time.

What happens to active runs when the daemon receives a shutdown signal?

The Shutdown method sets an internal shuttingDown flag, collects all active cancellation functions from the cancels map, and invokes each with a "daemon shutting down" error. It then blocks for up to 30 seconds, waiting for all run goroutines to signal completion via their done channels before allowing the process to exit.

How does the daemon handle recovery after a crash or unexpected termination?

During startup, recoverOnStartup in daemon.go marks any database runs stuck in non-terminal states as failed via db.RecoverStaleRuns, and walks the work-tree directory to remove orphaned directories that were left behind when the previous instance died.

Can clients subscribe to real-time updates while a pipeline is running?

Yes. The Subscribe method creates a buffered channel for event streaming and returns an unsubscribe function. Events are broadcast to all subscribers during execution, and channels are automatically closed when the run completes to prevent memory leaks and stale connections.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →