How Code Quality Standards Are Enforced in the no-mistakes Project

The no-mistakes project enforces code quality standards through a three-layer Lint step that combines configuration-driven commands, agent-driven housekeeping passes, and automated fix workflows to ensure every run either passes cleanly, auto-fixes safe issues, or blocks for human review.

The no-mistakes tool, developed in the kunchenguid/no-mistakes repository, treats code quality as a blocking pipeline concern rather than a cosmetic afterthought. Its enforcement mechanism operates through tightly coupled layers that span configuration management, AI agent interaction, and strict result handling to prevent any lint violation from slipping into the codebase.

The Three-Layer Enforcement Architecture

The project implements code quality standards through three distinct layers that execute for every pipeline run. Each layer handles a specific aspect of lint enforcement, from configuration overrides to runtime execution.

Configuration Layer

Per-repository overrides for lint commands are read from the Commands section of the merged configuration file (.no-mistakes.yaml). According to the source code in internal/config/config.go (lines 46-53), the system checks for a user-defined lint command before falling back to default behavior.

If no command is supplied in the configuration, the pipeline automatically triggers an agent-driven lint pass rather than failing silently. This fail-closed behavior ensures that code quality standards are always enforced, even without explicit user configuration.

Agent-Driven Housekeeping

When Commands.Lint is empty, the combined document and lint housekeeping pass runs once per pipeline round. As implemented in internal/pipeline/steps/lint.go (lines 22-32), this layer asks the agent to discover appropriate linters and formatters for the project, execute them, and return structured findings.

The results are cached in the shared HousekeepingLintResult structure. This cache is later consumed by the LintStep to avoid redundant agent invocations, optimizing performance while maintaining strict enforcement.

LintStep Execution

The core enforcement logic resides in internal/pipeline/steps/lint.go (lines 12-28), where the LintStep executes a four-phase process:

  1. Prompt generation – Constructs a detailed prompt instructing the agent to focus exclusively on lint, format, and static-analysis issues, explicitly forbidding test execution or broader validation.
  2. Agent run – The agent returns a JSON payload containing findings plus a concise commit-style summary.
  3. Result handling – Non-zero exit codes from external linters create blocking findings (NeedsApproval: true) and mark the step as AutoFixable.
  4. Auto-fix verification – When auto-fix is enabled, the step invokes the agent in fix mode, applies changes, and re-runs the external linter to verify resolution.

The strict prompting rules (lines 51-55 of lint.go) explicitly prohibit the agent from reporting issues it already fixed, refactoring beyond the root cause, or running tests, ensuring the step remains focused on code quality concerns only.

Auto-Fix and Approval Workflows

The enforcement system distinguishes between auto-fixable issues and those requiring human intervention. As defined in internal/types/findings.go (lines 22-40), findings are parsed into the internal types.Finding structure where blocking findings (categorized as error or warning) cause the pipeline to park and await human approval.

The auto-fix mechanism operates with configurable limits set via the AutoFix.Lint numeric value in .no-mistakes.yaml. This value determines how many automatic fix attempts are permitted before the step requires manual review. If the limit is exceeded or the fix fails verification, the pipeline blocks rather than allowing potentially degraded code to proceed.

When fixes are applied successfully, the agent must emit a one-sentence summary under ten words (such as "no-mistakes(lint): fix lint issues"), which becomes the git commit message. This requirement ensures auditability and readable project history.

Configuration Examples

Declaring Lint Commands

Configure project-specific linting via .no-mistakes.yaml:

commands:
  lint: "golangci-lint run ./..."
auto_fix:
  lint: 2          # allow up to two auto-fix attempts

The lint field maps to config.Commands.Lint in internal/config/config.go, while auto_fix.lint controls the retry limit enforced by the pipeline.

Prompt Construction

The following excerpt from internal/pipeline/steps/lint.go (lines 34-56) illustrates how the system constrains agent behavior to maintain code quality focus:

prompt := fmt.Sprintf(
    `Detect the linting and formatting tools for this project, run the relevant checks yourself, apply safe fixes, and verify the result.

Context:
- branch: %s
- base commit: %s
- target commit: %s

Task:
- Discover the configured linters and formatters for this repository.
- Only lint or format the relevant changed files when possible.
- Apply safe formatter, linter, and static-analysis fixes yourself.
- Re-run the relevant checks after fixing.
- Report only unresolved lint, format, or static-analysis issues as structured findings.
- If everything is clean or fixed, return an empty findings array.

Rules:
- Do not run tests or broader behavioral validation.
- Focus on lint, format, and static-analysis issues only.
- Do not report issues you already fixed.
- The summary must be one concise sentence fragment suitable for a git commit subject.
- Keep the summary under 10 words.%s`,
    sctx.Run.Branch, baseSHA, sctx.Run.HeadSHA, reassessHistory,
)

Auto-Fix Implementation

The fix workflow in internal/pipeline/steps/lint.go (starting at line 104) demonstrates how the pipeline handles remediation:

if sctx.Fixing {
    // ask the agent to fix lint issues first
    summary, err := executeFixMode(sctx, s.Name(), fixExecutionOptions{
        LogMessage: "asking agent to fix lint issues...",
        Prompt:     fixPrompt,
        ErrorPrefix: "agent fix lint",
        FallbackSummary: "fix lint issues",
    })
    // commit the fixes and re-run the external linter
}

Summary

  • Three-layer architecture: Configuration overrides, agent-driven housekeeping, and LintStep execution work together to enforce standards without gaps.
  • Fail-closed defaults: Missing lint commands trigger agent discovery rather than skipping validation, ensuring continuous enforcement.
  • Structured findings: The types.Finding system categorizes violations and blocks the pipeline on errors while reporting informational issues.
  • Controlled auto-fix: The AutoFix.Lint configuration limits automatic remediation attempts and requires human approval when exceeded.
  • Auditability requirements: All fixes generate concise commit messages under ten words, maintaining transparent project history.

Frequently Asked Questions

What happens if I don't configure a lint command in .no-mistakes.yaml?

If no commands.lint value is provided, the pipeline executes an agent-driven housekeeping pass that discovers and runs appropriate linters automatically. This cached result is then consumed by the LintStep, ensuring code quality standards are enforced even without explicit configuration. The system fails closed rather than allowing unlinted code to pass.

How does the no-mistakes project prevent auto-fixes from introducing new bugs?

The auto-fix workflow limits the number of attempts via the AutoFix.Lint configuration value. After applying fixes, the step re-runs the external lint command to verify the issues are resolved. Additionally, the agent is strictly prompted to apply only "safe" fixes and to avoid refactoring beyond the root cause, minimizing the risk of behavioral changes.

Can the lint step be bypassed if the agent fails to execute?

No. If the lint command is missing and the shared HousekeepingLintResult cannot be parsed from the cache, the step forces a human approval via documentApprovalOutcome. This guarantees that technical failures in the agent or external tools cannot be used to circumvent code quality enforcement.

Where are lint violations stored for review?

Lint findings are parsed into the types.Finding structure defined in internal/types/findings.go. These findings carry metadata including severity levels and NeedsApproval flags. Blocking findings (errors and warnings) park the pipeline and surface in the review interface, while the underlying data structure supports programmatic access for custom reporting integrations.

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 →