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:
-
Initial Pass – The step runs once and produces its initial set of findings.
-
Auto-Fix Round Creation – If the step’s configured limit is greater than zero, the executor creates a new round with
Trigger = "auto_fix"(seeround.golines 7‑15) and invokes the step again with fixes applied from the previous round. -
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.golines 305‑314). -
Review Step Protection – Because
auto_fix.reviewdefaults 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 globalauto_fix.review > 0override is required to enable auto-fix for review (seeaxi_render.goline 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:
-
The executor loads the resolved
AutoFixstruct fromconfig.go, dereferencing the pointer values fromAutoFixRaw. -
For each step, it checks
Config.AutoFixto determine the maximum number of auto-fix rounds permitted. -
If the step reports findings and the current round count is below the limit,
executor.gotriggers a new round withRoundSelectionSourceAutoFixand callsIsAutoFix()to tag the database entry. -
Once the limit is reached, the executor halts auto-fix attempts and, if findings remain, invokes the rendering logic in
axi_render.goto display the awaiting-approval message.
Summary
- Auto-fix limits are integer values in the
auto_fixconfiguration 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.golines 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.golines 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →