How Auto-Fix Limits Control Findings in no-mistakes

No-mistakes uses integer auto-fix limits configured in the auto_fix section to cap how many automatic resolution attempts each pipeline step (lint, test, review, etc.) may perform before pausing for manual approval.

The kunchenguid/no-mistakes repository implements a deterministic pipeline executor that attempts to self-heal findings through automated rounds. These auto-fix limits prevent infinite loops by strictly controlling how many times a step can re-run after applying its own fixes.

What Are Auto-Fix Limits in no-mistakes?

Auto-fix limits are integer values stored in the auto_fix configuration section that define the maximum number of follow-up attempts a step receives after its initial run. According to the source code in config.go (lines 94‑106), these limits are defined in the raw configuration (AutoFixRaw) as pointer fields so the system can distinguish between "not set" and an explicit zero. When resolved, they dereference into an AutoFix struct.

Each pipeline step has its own configurable limit:

Step Configuration Key Default Behavior
Lint auto_fix.lint 3 Re-runs lint up to 3 times after the initial pass, applying fixes each round.
Test auto_fix.test 3 Same iterative behavior for the test step.
Review auto_fix.review 0 Disabled by default; findings never auto-fix unless explicitly enabled.
Document auto_fix.document 3 Controls auto-fixes for generated documentation passes.
CI auto_fix.ci 3 Limits auto-fixes for CI-related findings such as flaky tests.
Rebase auto_fix.rebase 3 Allows auto-fix rounds after a rebase to resolve new issues.
Babysit auto_fix.babysit Not exposed Controls attempts for the babysit step, but lacks a default configuration value.

How Auto-Fix Limits Control Findings

The executor respects these limits through a strict round-based lifecycle that determines whether findings are automatically resolved or parked for human review.

The Auto-Fix Round Lifecycle

The process follows three distinct phases as implemented in round.go and executor.go:

  1. Initial Pass – The step runs once and produces its initial set of findings.

  2. Auto-Fix Round Creation – If the step’s configured limit is greater than zero, the executor creates a new round with Trigger = "auto_fix" (see round.go lines 7‑15) and invokes the step again with fixes applied from the previous round.

  3. Round Counter Enforcement – Each auto-fix round increments the counter. The executor stops spawning new rounds when the count reaches the configured limit. Importantly, the limit counts follow-up attempts, not the initial run.

Findings Handling and Approval Gates

When the pipeline processes these rounds, it uses the limits to determine the final state of the run:

  • Successful Resolution – If a round succeeds, the updated findings replace the previous set and the pipeline proceeds to the next step.

  • Limit Reached with Remaining Findings – If the limit is exhausted while findings persist, the pipeline parks the run at an awaiting-approval gate, surfacing the remaining findings to the user (see axi_render.go lines 305‑314).

  • Review Step Protection – Because auto_fix.review defaults to 0, any blocking or ask-user findings are shown immediately and never auto-fixed. The UI explicitly notes this behavior, stating that a repo or global auto_fix.review > 0 override is required to enable auto-fix for review (see axi_render.go line 305).

Configuring Auto-Fix Limits

You can override defaults in your repository-specific .no-mistakes.yaml file. Because the configuration uses pointer fields in AutoFixRaw, explicitly setting a value to 0 disables the feature, while omitting the key allows the default to apply.


# .no-mistakes.yaml

auto_fix:
  lint: 2          # Allow up to 2 auto-fix attempts after initial lint

  test: 1          # Only one auto-fix round for tests

  review: 3        # Enable auto-fix for review (overrides default 0)

  document: 0      # Disable document auto-fix entirely

  ci: 2
  rebase: 4

When the pipeline runs, the executor reads these values via Config.AutoFix and uses them to decide whether to spawn an auto_fix round. The round is persisted in the SQLite round table with trigger = "auto_fix", as defined in round.go.

Step-by-Step Execution Flow

The interaction between configuration and execution works as follows:

  1. The executor loads the resolved AutoFix struct from config.go, dereferencing the pointer values from AutoFixRaw.

  2. For each step, it checks Config.AutoFix to determine the maximum number of auto-fix rounds permitted.

  3. If the step reports findings and the current round count is below the limit, executor.go triggers a new round with RoundSelectionSourceAutoFix and calls IsAutoFix() to tag the database entry.

  4. Once the limit is reached, the executor halts auto-fix attempts and, if findings remain, invokes the rendering logic in axi_render.go to display the awaiting-approval message.

Summary

  • Auto-fix limits are integer values in the auto_fix configuration section that cap follow-up attempts per pipeline step.
  • Default limits are 3 for lint, test, document, CI, and rebase, but review is disabled by default (limit 0).
  • Pointer fields in AutoFixRaw (config.go) allow the system to distinguish between unset values and explicit zero.
  • Round creation uses Trigger = "auto_fix" (round.go lines 7‑15) and increments until the limit is reached.
  • Limit enforcement parks runs at an awaiting-approval gate when findings persist after the final allowed round (axi_render.go lines 305‑314).

Frequently Asked Questions

Why is the review auto-fix limit set to 0 by default?

The review step defaults to 0 to prevent automatic application of code changes that might require human judgment. According to axi_render.go line 305, this ensures that review findings—often involving architectural decisions or security concerns—are surfaced immediately to the user rather than silently patched by automation.

How does no-mistakes distinguish between unset and explicitly zero limits?

The configuration system uses pointer fields in the AutoFixRaw struct defined in config.go (lines 94‑106). A nil pointer indicates the value is unset (allowing the global default), while a pointer to 0 explicitly disables auto-fix for that step. During resolution, these pointers dereference into the concrete AutoFix struct used by the executor.

What happens when an auto-fix limit is reached but findings remain?

When the round counter reaches the configured limit and the step still reports findings, the executor parks the pipeline run at an awaiting-approval gate. As implemented in axi_render.go (lines 305‑314), the UI displays the remaining findings and requires manual user intervention before the pipeline can proceed.

Can I disable auto-fix for specific steps entirely?

Yes. Set the specific step’s limit to 0 in your .no-mistakes.yaml configuration file. For example, setting auto_fix.document: 0 disables automatic fixing for documentation generation. This explicit zero overrides any default value, preventing the executor from spawning any auto-fix rounds for that step.

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 →