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

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. 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 (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 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:

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 (lines 50–63), this method resolves the effective action for any finding:

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 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 and internal/pipeline/steps/document.go to handle their respective findings independently.

Rendering and UI Representation

The terminal UI in 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:

// 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 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. 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 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.

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 →