# How Findings Are Categorized in no-mistakes: Understanding Category and actionOrDefault

> Discover how no-mistakes categorizes findings using Category and Action fields. Learn about actionOrDefault and how it ensures no silent fixes, improving your workflow.

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

---

**In the no-mistakes codebase, every Finding is classified by a `Category` field (documentation or lint) for pipeline routing and an `Action` field (no-op, auto-fix, or ask-user) for resolution behavior, with the `actionOrDefault()` method ensuring empty actions default to `"ask-user"` to prevent silent automatic fixes.**

The `no-mistakes` repository treats every review result, test output, lint error, and PR comment as a **Finding** defined in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go). Understanding how these findings are categorized and how their actions are resolved is critical for contributing to or extending the pipeline. The system uses two orthogonal classification mechanisms to determine both which gate processes a finding and how the pipeline ultimately handles it.

## Finding Classification Architecture

Every `Finding` struct carries two distinct classification fields that serve different purposes in the pipeline. The `Category` field determines which housekeeping gate owns the finding, while the `Action` field controls the resolution strategy.

### Category-Based Gate Routing

The `Category` field routes findings to the appropriate processing gate during the combined document and lint housekeeping pass. This classification uses two constants defined in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) (lines 33–39):

- **`FindingCategoryDocumentation`** (empty string `""`): Indicates the finding belongs to the documentation gate
- **`FindingCategoryLint`** (`"lint"`): Indicates the finding belongs to the lint gate

When `Category` is empty, the pipeline treats the finding as a documentation issue. This design allows the housekeeping step in [`internal/pipeline/steps/housekeeping_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/housekeeping_test.go) to split its work across the two gates efficiently.

### Action-Based Resolution Strategy

The `Action` field determines how the pipeline treats the finding after production. The system defines three action constants:

```go
const (
    ActionNoOp    = "no-op"    // informational only, never fixed
    ActionAutoFix = "auto-fix" // safe to apply automatically
    ActionAskUser = "ask-user" // requires human intervention
)

```

These actions control whether a finding is silently ignored, automatically corrected, or parked for human review.

## Understanding the actionOrDefault() Method

The `actionOrDefault()` method implements a safety mechanism to prevent undocumented findings from being auto-fixed. Located in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) (lines 50–63), this method resolves the effective action for any finding:

```go
func (f Finding) actionOrDefault() string {
    if f.Action == "" {
        return ActionAskUser // default
    }
    return f.Action
}

```

When a finding's `Action` field is empty, the method supplies the **default** action `"ask-user"`. This guards against silently auto-fixing legacy or unclassified findings and aligns with the review prompt's principle of "when in doubt, default to ask-user". The [`internal/pipeline/steps/review.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/review.go) file utilizes `HasAskUserFindings()`, which internally calls `actionOrDefault()`, to determine whether to park a run for human review.

## Practical Implementation in the Pipeline

The categorization system manifests across multiple pipeline steps to coordinate processing and resolution.

### Housekeeping and Gate Assignment

The housekeeping pass uses the `Category` field to partition findings between documentation and lint processing. As implemented in the pipeline steps, findings with `Category = FindingCategoryLint` route to the lint gate, while those with empty categories route to the documentation gate. This separation allows [`internal/pipeline/steps/lint.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/lint.go) and [`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go) to handle their respective findings independently.

### Rendering and UI Representation

The terminal UI in [`internal/tui/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/tui/findings.go) renders both the category and resolved action for each finding, giving users visibility into how the system classified each issue and how it intends to resolve it.

## Working with Findings in Code

When creating findings programmatically, you explicitly set the classification fields or rely on the default behavior:

```go
// Create a lint finding that will be auto-fixed.
f := types.Finding{
    Severity:    "high",
    Description: "Trailing whitespace",
    Action:      types.ActionAutoFix,
    Category:    types.FindingCategoryLint,
}

// Create a documentation finding without an explicit action.
// The pipeline will treat it as "ask-user" because actionOrDefault()
// supplies the default.
g := types.Finding{
    Severity:    "info",
    Description: "Missing Javadoc comment",
    // Action omitted → defaults to ask-user
    Category:    types.FindingCategoryDocumentation,
}

// Resolve the effective actions.
fmt.Println(f.Action)                 // "auto-fix"
fmt.Println(g.Action)                 // "" (empty)
fmt.Println(g.actionOrDefault())      // "ask-user"

```

## Summary

- **Finding categorization** in `no-mistakes` uses a `Category` field (empty for documentation, `"lint"` for lint) to route findings to the appropriate housekeeping gate.
- **Action resolution** relies on three explicit constants: `ActionNoOp`, `ActionAutoFix`, and `ActionAskUser`.
- **Safety default**: The `actionOrDefault()` method in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) returns `"ask-user"` when no action is specified, preventing accidental auto-fixes of unclassified findings.
- **Pipeline integration**: The review step uses `HasAskUserFindings()` (which calls `actionOrDefault()`) to determine if human intervention is required before proceeding.

## Frequently Asked Questions

### What is the default action for findings in no-mistakes?

When a finding has no explicit `Action` field set, the `actionOrDefault()` method defaults to `"ask-user"`. This ensures that any unclassified or legacy finding requires human review rather than being automatically fixed or silently ignored.

### How does no-mistakes differentiate between documentation and lint findings?

The system uses the `Category` field defined in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go). An empty `Category` (represented by `FindingCategoryDocumentation`) indicates a documentation finding, while the string `"lint"` (represented by `FindingCategoryLint`) indicates a lint finding. The housekeeping pass uses this distinction to split processing across the two gates.

### What happens if a finding has no explicit Category assigned?

If the `Category` field is empty, the pipeline treats the finding as belonging to the documentation gate. This is the default state for findings produced by the document processing step, while the lint step explicitly sets `Category = FindingCategoryLint`.

### Where is the actionOrDefault() method defined?

The `actionOrDefault()` method is defined in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) at lines 50–63. This method checks if `f.Action` is empty and returns `ActionAskUser` as the default, otherwise returning the explicitly set action value.