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

> Learn how no-mistakes automatically fixes code issues. Discover its pipeline execution, configurable limits, and audit trails for efficient resolution.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: how-to-guide
- Published: 2026-06-28

---

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

```go
// 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`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go)** (lines 95‑104). The `autoFixDefaults()` function returns an `AutoFix` struct with predefined thresholds:

```go
// 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`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/executor.go)** (lines 317‑323). After each step execution, the code evaluates whether to trigger an auto-fix pass:

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