# How the no-mistakes Daemon Manages Runs and Its Lifecycle

> Discover how the no-mistakes daemon manages runs and lifecycle. Learn about centralized RunManager, thread-safe maps, mutex locks, and deferred cleanup for efficient pipeline orchestration.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: internals
- Published: 2026-06-27

---

**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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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:

```go
// 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.

```go
// 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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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.