How no-mistakes Handles Auto-Fixing Findings: Pipeline Execution and Configuration

no-mistakes automatically resolves code-style and lint findings by filtering for the "auto-fix" action, re-executing pipeline steps up to a configurable limit, and persisting each attempt with full audit trails in the database.

The no-mistakes repository implements a deterministic auto-fix workflow that eliminates manual toil for trivial issues. By analyzing step outcomes and re-running executions with fix context, the system resolves problems automatically while respecting guardrails and maintaining complete observability.

Identifying Auto-Fixable Findings

The pipeline distinguishes between findings that require human review and those that can be resolved automatically. In internal/pipeline/findings.go (lines 22‑38), the autoFixableFindingsJSON function filters raw JSON findings to extract only items where the Action field equals "auto-fix".

// internal/pipeline/findings.go
func autoFixableFindingsJSON(raw string) string {
    if raw == "" { return "" }
    findings, err := types.ParseFindingsJSON(raw)
    if err != nil { return raw }
    fixable := types.AutoFixableFindings(findings) // keeps only Action=="auto-fix"
    if len(fixable.Items) == 0 { return "" }
    fixableRaw, err := types.MarshalFindingsJSON(fixable)
    if err != nil { return raw }
    return fixableRaw
}

If the filtered list contains entries, the executor receives a non-empty payload indicating that automatic remediation is possible.

Configuring Auto-Fix Limits

Each pipeline step type has a default retry limit defined in internal/config/config.go (lines 95‑104). The autoFixDefaults() function returns an AutoFix struct with predefined thresholds:

// internal/config/config.go
func autoFixDefaults() AutoFix {
    return AutoFix{
        Lint:     3,
        Test:     3,
        Review:   0,
        Document: 3,
        CI:       3,
        Rebase:   3,
    }
}

Users override these defaults via the auto_fix section in YAML configuration files. The merged configuration is accessed at runtime through Config.AutoFixLimit(stepName), which returns the maximum attempts allowed for the current step.

The Auto-Fix Execution Loop

The core orchestration logic resides in Executor.executeStep within internal/pipeline/executor.go (lines 317‑323). After each step execution, the code evaluates whether to trigger an auto-fix pass:

// internal/pipeline/executor.go (excerpt)
autoFixLimit := e.config.AutoFixLimit(stepName)
autoFixAttempts := 0
for {
    outcome, err := step.Execute(sctx)
    // … (store findings, etc.)
    if outcome.AutoFixable && autoFixLimit > 0 && autoFixAttempts < autoFixLimit {
        fixableFindings := autoFixableFindingsJSON(outcome.Findings)
        if fixableFindings != "" {
            autoFixAttempts++
            telemetry.Track("fix", e.fixTelemetryFields("auto", stepName,
                findingsCount(fixableFindings), autoFixAttempts))
            // record selection for DB
            if currentRoundID != "" {
                idsJSON := findingIDsJSON(fixableFindings)
                e.db.SetStepRoundSelection(currentRoundID, &idsJSON,
                    db.RoundSelectionSourceAutoFix)
            }
            // mark step as fixing and re‑run
            e.db.UpdateStepStatus(sr.ID, types.StepStatusFixing)
            sctx.Fixing = true
            sctx.PreviousFindings = fixableFindings
            nextTrigger = "auto_fix"
            continue
        }
    }
    // … proceed to approval or finish
}

The loop continues only when three conditions are met: the step reports outcome.AutoFixable as true, the configured limit is greater than zero, and the current attempt count remains below that limit.

Agent Context and Fix Application

During the auto-fix pass, the executor modifies the step context (sctx) to signal that the current execution is a remediation attempt. The code sets sctx.Fixing = true and populates sctx.PreviousFindings with the filtered JSON payload. Step implementations read these fields to invoke appropriate agent commands—such as linting tools with --fix flags or code formatters—that modify the repository content directly.

Telemetry and Audit Trails

Every auto-fix attempt generates observability data. The executor calls telemetry.Track("fix", …) with metadata including the step name, attempt number, and finding count. Simultaneously, the database records the selection via db.SetStepRoundSelection, associating the finding IDs with the source constant RoundSelectionSourceAutoFix. This persistence enables UI components to display auto-fix statistics—such as "auto-fixed (2)"—in PR summaries and dashboards.

Termination Conditions

The auto-fix loop exits when either no more auto-fixable findings remain (empty fixableFindings payload) or the attempt counter reaches the configured limit (autoFixAttempts >= autoFixLimit). Upon termination, the pipeline proceeds to the standard approval flow for any remaining non-fixable findings, or marks the step as successfully completed if all issues are resolved.

Summary

  • Detection: autoFixableFindingsJSON in internal/pipeline/findings.go filters for findings with Action: "auto-fix".
  • Limits: Default caps are defined in autoFixDefaults (e.g., 3 for Lint, 0 for Review) and overridable via YAML configuration.
  • Execution: The Executor.executeStep loop in internal/pipeline/executor.go re-runs steps up to the limit, passing fix context via sctx.Fixing and sctx.PreviousFindings.
  • Observability: Each attempt is tracked via telemetry.Track and persisted to the database with SetStepRoundSelection for audit purposes.

Frequently Asked Questions

What types of findings can no-mistakes auto-fix?

no-mistakes can only auto-fix findings explicitly marked with the Action field set to "auto-fix" in the step's JSON output. Typically these include code-style violations, formatting issues, and certain linting errors that have deterministic, safe corrections.

How does the configuration limit auto-fix attempts?

The system reads Config.AutoFixLimit for each step type, using defaults from autoFixDefaults() in internal/config/config.go. You can override these per-repository or globally in the auto_fix section of your configuration YAML to set custom thresholds or disable auto-fix entirely by setting the value to zero.

Where does no-mistakes store the history of auto-fix attempts?

Each attempt is recorded in the database via db.SetStepRoundSelection with the source identifier RoundSelectionSourceAutoFix, and telemetry events are emitted via telemetry.Track("fix", …). This dual recording provides both an audit trail for compliance and metrics for the UI to display auto-fix counts in pull request summaries.

Can specific pipeline steps disable auto-fixing while others allow it?

Yes. Since limits are configured per step type in the AutoFix struct (Lint, Test, Review, Document, CI, Rebase), you can set individual thresholds such as Review: 0 to disable auto-fixing for code review steps while allowing up to three attempts for linting 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 →