How the no-mistakes Pipeline Executor Handles Findings and Auto-Fix Logic

The no-mistakes pipeline executor collects findings from each step, classifies them using helper functions in internal/types/findings.go, and routes actionable items to either an automated correction loop or a human-review queue depending on the Action field.

The kunchenguid/no-mistakes repository implements a deterministic CI/CD system where the pipeline executor serves as the central orchestrator. This component manages the lifecycle of findings—from collection through classification to resolution—ensuring that only safe, pre-approved changes are applied automatically while mandatory review items pause the workflow.

Findings Representation and Classification

All findings travel through the system as a strongly-typed types.Findings struct defined in [internal/types/findings.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go). Each finding carries metadata including Severity, Description, Action, and RequiresHumanReview.

Two helper functions drive the executor’s routing decisions:

These pure functions allow the executor to make deterministic routing decisions without inspecting individual finding internals directly.

Executor Initialization and Configuration

The executor is instantiated via pipeline.NewExecutor (see [internal/pipeline/executor.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/executor.go#L69)). During construction, it receives:

The executor also initializes memory structures to track awaiting_agent_since timestamps when human review is required.

Step Execution and Finding Normalization

When an agent step completes, the executor receives a StepResult containing raw findings. Before routing, the executor:

  1. Normalizes IDs – calls NormalizeFindings (line 104 in [findings.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go#L104)) to ensure every finding has a deterministic identifier, guaranteeing stable merge behavior across rounds
  2. Persists the round – writes the findings JSON to the database round record so the UI can render them on resume
  3. Broadcasts state – emits a StepCompleted event to listeners, including the TUI renderer tested in [internal/tui/viewport_test.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/tui/viewport_test.go)

Decision Logic: Auto-Fix vs Human Review

After collecting normalized findings, the executor applies a strict priority check:

if types.HasAskUserFindings(findings) {
    // Human review required: park the run and set awaiting_agent_since
    exec.parkRun(runID, findings)
    return
} else if autoFix := types.AutoFixableFindings(findings); len(autoFix.Items) > 0 {
    // Safe to auto-fix: enter the correction loop
    exec.runAutoFixLoop(ctx, runID, autoFix)
}

If any ask-user findings exist, the executor immediately parks the run (updating awaiting_agent_since in the database as seen in [internal/db/run.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/run.go#L23)) and waits for external approval via the daemon’s HandleRespond method (line 848 in [internal/daemon/manager.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go#L848)).

The Auto-Fix Loop Implementation

When findings contain only auto-fix actions (or mixed no-op items), the executor enters a loop that applies corrections iteratively:

for {
    // Create a fix-specific round referencing the original finding ID
    fixRound := exec.createFixRound(ctx, runID, finding)
    
    // Invoke the step's agent with a fix prompt
    output, err := agent.Fix(ctx, finding)
    
    // Merge any new findings emitted by the agent
    merged := types.MergeUserOverrides(current, nil, output.Findings.Items)
    // MergeUserOverrides preserves user-added items with source:"user" (line 170 in findings.go)
    
    // Persist the updated state
    db.SaveRound(fixRound.ID, merged)
    
    // Continue until no auto-fixable items remain
    if len(types.AutoFixableFindings(merged).Items) == 0 {
        break
    }
}

Each iteration creates a new round in the database, allowing the UI to display progress and enabling recovery if the process restarts mid-fix. The loop respects the global auto_fix configuration flag; if disabled, AutoFixableFindings are treated as standard findings requiring human approval.

Integration with the Daemon and UI

The executor operates within the daemon context managed by [internal/daemon/manager.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go). Key integration points include:

  • Event Broadcasting – The executor pushes StepCompleted and AwaitingApproval events to the TUI, which renders the "awaiting approval" badge tested in [viewport_test.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/tui/viewport_test.go)
  • User Responses – When a user approves findings via the axi CLI, HandleRespond routes the approval back to the specific executor instance, which then resumes the pipeline
  • Cancellation – The manager can signal cancellation to the executor, which gracefully stops the auto-fix loop after the current agent invocation completes

Edge Cases and Guarantees

Scenario Executor Behavior
No findings Proceeds to next step immediately
Only no-op findings Treated as non-actionable; step marked approved
Mixed ask-user and auto-fix Presence of any ask-user forces parking; auto-fix deferred until human items resolved
Missing finding IDs NormalizeFindings generates deterministic UUIDs pre-routing
User-added findings MergeUserOverrides stamps with source:"user", preventing re-auto-fix
Executor restart Reloads last persisted round from DB; resumes auto-fix loop or awaiting-approval state

Summary

  • The no-mistakes pipeline executor operates as a finite state machine that transitions between running steps, awaiting human approval, and auto-fixing findings
  • AutoFixableFindings and HasAskUserFindings (lines 156 and 220 in findings.go) provide the classification logic that determines routing
  • Auto-fix loops are iterative, creating new database rounds for each correction attempt until no actionable items remain
  • Human-review findings trigger an immediate park state via awaiting_agent_since (line 23 in run.go), integrating with the daemon’s HandleRespond endpoint (line 848 in manager.go)
  • Deterministic IDs via NormalizeFindings (line 104) ensure stable merge behavior across pipeline restarts

Frequently Asked Questions

How does the executor prevent auto-fixing items that require human judgment?

The executor checks HasAskUserFindings before entering the auto-fix loop. If this function returns true—indicating any finding has Action: "ask-user"—the executor immediately parks the run and sets awaiting_agent_since in the database. This guarantees that human-review items block the pipeline regardless of whether other auto-fix items exist in the same result set.

What happens if the no-mistakes daemon restarts during an auto-fix loop?

The executor persists every round—including intermediate fix rounds—to the database via the *db.DB handle. On restart, the executor reloads the last persisted round for the active run, inspects the findings using AutoFixableFindings, and either resumes the fix loop or restores the awaiting-approval state. This design ensures exactly-once semantics for fix attempts and prevents duplicate agent invocations.

Can multiple auto-fix passes occur for a single original finding?

Yes. The auto-fix loop continues invoking the agent and creating new rounds until AutoFixableFindings returns zero items. If an agent’s fix attempt introduces a new detectable issue (for example, a lint error in the generated code), that new finding enters the next iteration. The loop breaks only when the output contains exclusively no-op or non-actionable findings.

Where is the auto-fix behavior configured, and can it be disabled per-run?

Global defaults reside in [internal/config/config.go](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go) under the auto_fix key. If this configuration is set to false, the executor treats findings with Action: "auto-fix" as requiring human review, effectively disabling the automatic correction loop. The executor checks this flag before calling runAutoFixLoop, ensuring the behavior is consistent across all pipeline steps.

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 →