# How no‑mistakes Handles Different Types of Code Errors: Severity, Action, and Category Explained

> Discover how no-mistakes classifies code errors by severity, action, and category. Streamline your workflow by auto-resolving mechanical issues and pausing for human review when needed.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: deep-dive
- Published: 2026-07-11

---

**`no‑mistakes` classifies code errors using three orthogonal dimensions—**Severity**, **Action**, and **Category**—to route issues through a multi‑step pipeline that can auto‑resolve mechanical problems or pause for human review when judgment is required.**

The open‑source tool `no‑mistakes` (`kunchenguid/no‑mistakes`) treats error handling as a data pipeline. Instead of failing fast on the first lint violation or test failure, it aggregates findings from four stages—**review**, **test**, **lint**, and **document**—into a unified type system defined in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go). By decoupling how bad a problem is from how it should be fixed, the architecture ensures that missing metadata always defaults to a safe **ask‑user** outcome, preventing silent regressions.

## The Three Dimensions of Error Classification

Every problem detected by the pipeline is stored as a `Finding` struct that carries three independent pieces of metadata. Together these fields determine whether the tool can merge a fix automatically or must surface the issue to a human.

### Severity

The `Severity` field communicates the impact of the problem. The review step uses three levels that map directly onto risk assessment later:

- **`error`** – Must not be merged; blocks the pipeline.
- **`warning`** – Nice to fix; does not block but is reported.
- **`info`** – Optional suggestion; purely informational.

### Action

The `Action` field (or the legacy `requires_human_review` boolean) tells the executor what to do with the finding. The three canonical actions are:

- **`auto‑fix`** – Mechanical code‑quality fixes (e.g., unused imports, formatting) that require no human judgment.
- **`ask‑user`** – Functional‑requirement or intent‑related issues that need human approval.
- **`no‑op`** – Informational only; no remediation required.

If a step omits the `Action` field, the helper `actionOrDefault()` guarantees a safe fallback to **ask‑user**.

### Category

Available only in the combined *document‑plus‑lint* pass, the `Category` field separates findings into:

- **`documentation`** – Generated by `DocumentStep`; never auto‑fixed.
- **`lint`** – Generated by `LintStep`; may be auto‑fixed if mechanical.

## Core Types and Helper Functions

The **core type** lives in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go). It defines the `Finding` struct, the `Severity` and `Action` constants, and four critical helper predicates that drive the execution engine:

- **`actionOrDefault()`** – Returns `ask‑user` when the action field is missing, ensuring safety by default.
- **`AutoFixableFindings()`** – Filters a slice to return only items with `Action == auto‑fix`, which are sent to the fix agent.
- **`HasAskUserFindings()`** – Returns `true` if any finding requires human review, causing the TUI to pause for approval.
- **`HasActionableFindings()`** – Returns `true` if any finding is not a `no‑op`, driving the auto‑resolve logic to distinguish between items that need work versus items that are purely informational.

## How Each Pipeline Step Interprets Errors

Each stage in the pipeline (`review`, `test`, `lint`, `document`) produces `Finding` values, but they populate the metadata differently based on the nature of the work.

### ReviewStep ([`internal/pipeline/steps/review.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/review.go))

The review step scans the diff, builds a detailed prompt, and asks the LLM to return structured JSON findings. The prompt enforces strict classification rules:

> “For each finding, set the **action** field to one of:  
> • **ask‑user** – functional‑requirement or intent‑related issue.  
> • **auto‑fix** – non‑functional, non‑user‑visible issue (correctness, error handling, security, performance, mechanical quality).  
> • **no‑op** – informational only.”

The LLM assigns `Severity` (`error`, `warning`, or `info`) based on impact, and the step passes the resulting JSON back to the executor.

### TestStep ([`internal/pipeline/steps/test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/test.go))

This step executes the user‑configured `commands.test` command. If the command exits with a non‑zero status, the step creates a single **error**‑severity finding with a generic description and marks the step with `NeedsApproval` and `AutoFixable` flags so the fix‑round can automatically retry after repairs.

### LintStep ([`internal/pipeline/steps/lint.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/lint.go))

The lint step runs the configured linter (or a combined document‑plus‑lint pass). It parses linter output into `Finding` structs and explicitly sets the **Category** field to `lint`. Like review findings, lint findings may be marked **auto‑fix** (e.g., removing unused imports) or **ask‑user** if they affect semantics.

### DocumentStep ([`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go))

This gate handles documentation‑only changes. Findings are always assigned the `documentation` category, and the step never produces an **auto‑fix** action because documentation edits are considered manual and require human verification.

## Auto‑Resolve Logic and Safety Guarantees

When the executor reaches the *auto‑resolve* phase, it inspects the merged `types.Findings` payload using the helper predicates from [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go):

```go
if types.HasAskUserFindings(findings) {
    // pause and present findings to the user for approval
}
if types.HasActionableFindings(findings) {
    // run the fix agents (auto-fix) or abort if only no‑ops remain
}

```

To create an error‑severity, auto‑fixable finding in a custom step, populate the struct as follows:

```go
f := types.Finding{
    Severity:    "error",
    File:        "pkg/foo.go",
    Line:        42,
    Description: "unused import",
    Action:      types.ActionAutoFix,               // safe to auto‑fix
    Category:    types.FindingCategoryLint,
}
findings := types.Findings{Items: []types.Finding{f}}
json, _ := types.MarshalFindingsJSON(findings)

```

To filter only the auto‑fixable items for the fix agent:

```go
autoFix := types.AutoFixableFindings(stepFindings)
summary, _ := types.MarshalFindingsJSON(autoFix)
// send `summary` to the LLM fix session

```

## Summary

- `no‑mistakes` uses **Severity** (error/warning/info) to signal urgency and **Action** (auto‑fix/ask‑user/no‑op) to decideRemediation strategy.
- The **Category** field isolates lint findings from documentation findings in combined passes.
- Core helper functions in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go)—`HasAskUserFindings()`, `HasActionableFindings()`, and `AutoFixableFindings()`—drive the executor’s decision to pause, fix, or proceed.
- Every pipeline step (`review`, `test`, `lint`, `document`) populates these fields according to domain‑specific rules, with the review step leveraging LLM prompting to classify issues correctly.
- Safety is enforced by `actionOrDefault()`, which ensures any ambiguous or missing action metadata defaults to **ask‑user**, preventing unintentional auto‑fixes of critical logic.

## Frequently Asked Questions

### What happens if a finding is missing the Action field?

The `actionOrDefault()` helper in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) intercepts the nil or empty value and returns **`ask‑user`**. This default prevents the pipeline from silently applying automatic fixes to issues that might require human judgment.

### Can documentation errors be auto‑fixed by no‑mistakes?

No. The `DocumentStep` ([`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go)) explicitly sets the `Category` to `documentation` and never assigns the `auto‑fix` action. Documentation changes are always surfaced to the user for manual approval, ensuring that public‑facing descriptions remain accurate and intentional.

### How does no‑mistakes handle test failures?

When the `TestStep` ([`internal/pipeline/steps/test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/test.go)) detects a non‑zero exit from the configured test command, it generates a single `Finding` with **`error`** severity, marks the step as `NeedsApproval`, and sets the `AutoFixable` flag. This allows the subsequent fix round to retry the tests automatically once the fix agents have applied mechanical repairs, but prevents merge until tests pass.

### What is the difference between actionable and auto‑fixable findings?

**Auto‑fixable** findings are those where `Action == auto‑fix`; these are sent to the LLM fix agents for mechanical remediation. **Actionable** findings are any findings that are not `no‑op`, including both `auto‑fix` and `ask‑user` items. The `HasActionableFindings()` predicate returns `true` if there is work to be done, while `HasAskUserFindings()` specifically detects the presence of high‑judgment issues that require human approval before the pipeline can continue.