# Architectural Patterns in no-mistakes: 11 Design Patterns Powering the AI-Driven Go Daemon

> Explore 11 architectural patterns in no-mistakes, including Command, Factory, and Strategy. Discover how these AI-driven Go daemon designs ensure extensibility and concurrency.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: architecture
- Published: 2026-07-11

---

**The no-mistakes project employs eleven distinct architectural patterns—including Command, Factory, Strategy, Pipeline, Observer, and Dependency Injection—to create an extensible, testable, and concurrent AI-driven pipeline system.**

The no-mistakes repository is a Go-based CLI application that runs as a long-lived daemon, orchestrating AI-driven steps through a sophisticated pipeline. By deliberately separating concerns and leveraging established architectural patterns, the codebase maintains safety under concurrent execution while remaining extensible for new AI providers and pipeline steps.

## Command Pattern: Structured CLI with Cobra

All user-facing commands in no-mistakes are built using the **cobra** framework, implementing the Command pattern. Each sub-command—such as `daemon start` or `axi run`—exists as a concrete command object that encapsulates its own execution logic and flag parsing.

In [`internal/cli/daemon_cmd.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/daemon_cmd.go), the `newDaemonCmd` function constructs the command hierarchy and wires each command's `RunE` handler:

```go
// internal/cli/daemon_cmd.go
func newDaemonCmd() *cobra.Command {
    cmd := &cobra.Command{
        Use:   "daemon",
        RunE: func(cmd *cobra.Command, args []string) error {
            // execution logic
        },
    }
    return cmd
}

```

## Singleton Pattern: Process-Wide Mutual Exclusion

To guarantee that only one daemon instance owns a given `NM_HOME` directory, no-mistakes implements a **Singleton** pattern through an exclusive OS file lock. The `acquireSingletonLock` function in [`internal/daemon/lock.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock.go) creates a process-wide lock before any destructive startup work begins.

```go
// internal/daemon/lock.go
lock, err := acquireSingletonLock(paths)
if err != nil {
    log.Fatalf("cannot start daemon: %v", err)
}
defer lock.Release()

```

This ensures mutual exclusion across processes, preventing concurrent daemon instances from corrupting shared state.

## Factory Pattern: Pluggable Step and Agent Creation

The architecture relies heavily on **Factory** methods to decouple object creation from usage, enabling runtime customization of the pipeline.

### StepFactory

The `StepFactory` type in [`internal/daemon/manager.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go) produces the ordered list of pipeline steps:

```go
type StepFactory func() []pipeline.Step

```

Callers can inject a custom factory or fall back to the default `steps.AllSteps` implementation, allowing teams to modify pipeline behavior without altering core logic.

### AgentFactory

Similarly, the `newPipelineAgent` function constructs agent chains (including steering and fallback layers) based on resolved configuration:

```go
func newPipelineAgent(ctx context.Context, cfg *config.Config) (agent.Agent, error)

```

## Strategy Pattern: Runtime Agent Selection

The **Strategy** pattern enables interchangeable AI providers at runtime. In [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go), the `ResolveAgent` method selects the concrete implementation—Claude, Codex, or others—based on configuration.

The selected strategy is then wrapped with steering logic and fallback chains in `newPipelineAgent`, allowing the pipeline core to remain agnostic of specific AI providers while supporting multiple strategies simultaneously.

## Pipeline and Chain-of-Responsibility: Step Execution Flow

The core execution engine implements a **Pipeline** pattern (a variant of Chain-of-Responsibility) where steps are linked in an ordered slice. Each step implements the `Step` interface defined in [`internal/pipeline/pipeline.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/pipeline.go):

```go
type Step interface {
    Name() types.StepName
    Execute(*StepContext) (*StepOutcome, error)
}

```

The executor iterates through the slice, handing control to each step sequentially via the `Execute` method. This structure allows steps to be added, removed, or reordered without modifying the execution engine.

## Observer Pattern: Asynchronous Event Broadcasting

For decoupling the daemon from its consumers, no-mistakes employs the **Observer** (Publish-Subscribe) pattern. The `RunManager` in [`internal/daemon/manager.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go) exposes a `Subscribe` method that registers channels for event delivery:

```go
sub, unsub := daemonManager.Subscribe(runID)
defer unsub()

for ev := range sub {
    fmt.Printf("Run %s event: %s\n", ev.RunID, ev.Type)
}

```

The `broadcast` method pushes events to all subscribers, enabling multiple UI or external listeners to receive updates without blocking the pipeline.

## State Pattern: Durable Session Management

Review and fix phases utilize the **State** pattern through `RunSessions`, which maintain durable session IDs per role (reviewer/fixer). The `StepContext.RunAgentSession` method in [`internal/pipeline/pipeline.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/pipeline.go) either initiates a cold run or reuses an existing session:

```go
func (ctx *StepContext) RunAgentSession(agent Agent, sessionID string) (Result, error)

```

This effectively switches between state objects based on availability, preserving context across pipeline iterations.

## Dependency Injection: Testable Component Wiring

The `RunManager` implements **Dependency Injection** through its constructor, `NewRunManager`, which explicitly receives implementations of the database layer, path utilities, and step factories:

```go
func NewRunManager(db db.DB, paths paths.Paths, factory StepFactory) *RunManager

```

This explicit wiring eliminates hidden global state and facilitates unit testing by allowing mock implementations to be injected during test execution.

## Context Cancellation: Graceful Shutdown Propagation

All long-running operations respect Go's `context.Context` for cancellation propagation. In [`internal/daemon/manager.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go), the `resumeRecoveredRun` function creates a cancellable context using `context.WithCancelCause`:

```go
runCtx, cancel := context.WithCancelCause(parentCtx)

```

This context flows through the entire pipeline, ensuring that shutdown signals propagate correctly to AI agents and subprocesses, enabling graceful termination.

## Adapter Pattern: Cross-Platform Abstraction

Platform-specific behaviors are isolated using the **Adapter** pattern through Go's build constraints. Files like [`internal/winproc/harden_windows.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/winproc/harden_windows.go) and [`internal/daemon/lock_unix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock_unix.go) provide OS-specific implementations selected at compile time:

- `*_windows.go` implements Windows service hardening
- `*_unix.go` implements Unix file locking

This approach presents a unified API to the rest of the application while handling platform differences transparently.

## Repository Pattern: Data Persistence Abstraction

The `internal/db` package implements the **Repository** pattern, providing a clean API for persistence without exposing SQL details to business logic. Functions like `GetActiveRuns` and `UpdateRunErrorStatus` abstract the underlying storage mechanism, allowing the daemon to interact with data through domain-oriented methods rather than database queries.

## Adding a Custom Pipeline Step

To extend the pipeline, implement the `Step` interface and register it in the factory:

```go
// mystep.go
type MyStep struct{}

func (s *MyStep) Name() types.StepName { return "my-step" }

func (s *MyStep) Execute(ctx *pipeline.StepContext) (*pipeline.StepOutcome, error) {
    // Custom logic
    return &pipeline.StepOutcome{ExitCode: 0}, nil
}

// Register in factory
func AllSteps() []pipeline.Step {
    return []pipeline.Step{
        &steps.Checkout{},
        &steps.MyStep{},  // New step
        &steps.Review{},
    }
}

```

## Summary

- **Command Pattern** structures the CLI using Cobra with discrete command objects for each operation.
- **Singleton Pattern** ensures single-daemon execution through OS-level file locking in [`internal/daemon/lock.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock.go).
- **Factory Pattern** decouples step and agent creation via `StepFactory` and `newPipelineAgent` in [`manager.go`](https://github.com/kunchenguid/no-mistakes/blob/main/manager.go).
- **Strategy Pattern** enables runtime selection of AI providers through `config.ResolveAgent`.
- **Pipeline Pattern** executes ordered steps via the `Step` interface in [`internal/pipeline/pipeline.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/pipeline.go).
- **Observer Pattern** facilitates asynchronous event broadcasting through `RunManager.Subscribe`.
- **State Pattern** manages durable agent sessions through `StepContext.RunAgentSession`.
- **Dependency Injection** makes `RunManager` testable via explicit constructor parameters.
- **Context Cancellation** ensures graceful shutdowns through `context.WithCancelCause`.
- **Adapter Pattern** handles platform differences via build-constrained files.
- **Repository Pattern** abstracts data access in the `internal/db` package.

## Frequently Asked Questions

### What is the purpose of the StepFactory in no-mistakes?

The `StepFactory` is a function type defined in [`internal/daemon/manager.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go) that produces a slice of `pipeline.Step` objects. It decouples the pipeline construction from execution, allowing developers to inject custom step sequences or modify the default `steps.AllSteps` behavior without changing the core daemon logic.

### How does no-mistakes ensure only one daemon runs at a time?

The application implements a **Singleton** pattern using an exclusive OS file lock. The `acquireSingletonLock` function in [`internal/daemon/lock.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/lock.go) creates a lock file in `NM_HOME` before startup, preventing multiple instances from running concurrently and potentially corrupting shared state.

### Can I swap the AI provider without modifying the core pipeline?

Yes. The **Strategy** pattern implemented in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go) via `ResolveAgent` allows runtime selection of AI providers (Claude, Codex, etc.). The selected agent is wrapped with steering and fallback logic in `newPipelineAgent`, enabling interchangeable strategies without altering the pipeline's step execution code.

### How does the daemon communicate progress to the CLI?

Communication uses the **Observer** pattern through the `RunManager.Subscribe` method. The CLI registers a channel to receive events, and the daemon broadcasts updates asynchronously via the `broadcast` method. This decouples the producer (daemon) from consumers (CLI, UI) and supports multiple simultaneous listeners.