# How Findings from Pipeline Steps Are Processed in no-mistakes

> Discover how no-mistakes processes pipeline findings by encoding them into JSON within StepOutcome structs. Learn about parsing, normalizing, and evaluating for auto-fix or human review.

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

---

**no-mistakes handles findings from pipeline steps by encoding them as JSON within StepOutcome structs, then parsing, normalizing, and evaluating them through actionability predicates to determine whether to auto-fix, request human review, or mark the step as successful.**

The `no-mistakes` repository implements a robust pipeline execution engine where discrete steps—such as test, lint, review, and rebase—generate structured findings that drive automation decisions. Each step produces a **StepOutcome** containing a JSON-encoded findings payload, which the executor processes through a deterministic workflow to manage code quality interventions safely.

## The StepOutcome Payload Structure

Each pipeline step constructs a `types.Findings` struct and marshals it into the outcome’s payload. In [`internal/pipeline/steps/test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/test.go), the test step builds findings containing a human-readable summary and optional artifact metadata:

```go
// internal/pipeline/steps/test.go
findings := types.Findings{
    Summary: result.Text,           // Description of test results
    Tested:  tested,                // []string of test artifact labels
}
findingsJSON, _ := json.Marshal(findings)

outcome := &pipeline.StepOutcome{
    Findings:   string(findingsJSON), // JSON payload sent to executor
    FixSummary: fixSummary,
}

```

The `types.Findings` struct serves as the canonical wire format. Steps like review ([`internal/pipeline/steps/review.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/review.go)) and rebase ([`internal/pipeline/steps/rebase.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/rebase.go)) follow this same pattern, creating specialized findings for code review issues or merge conflicts respectively.

## Parsing and Normalizing Findings

When the executor receives a `StepOutcome`, it converts the JSON string back into structured data using `types.ParseFindingsJSON`. Located in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) (lines 89-100), this function handles both the current wire format and legacy keys like `items` for backward compatibility.

After parsing, the executor calls `types.NormalizeFindings` to assign deterministic identifiers to any finding lacking an explicit ID. This function generates stable IDs using the pattern `<prefix>-<n>` (e.g., `test-1`, `lint-2`), ensuring consistent referencing during filtering and user interaction:

```go
// internal/pipeline/executor.go (simplified)
func (e *Executor) handleOutcome(out *pipeline.StepOutcome, stepName string) error {
    // Decode JSON payload
    f, err := types.ParseFindingsJSON(out.Findings)
    if err != nil {
        return err
    }

    // Assign deterministic IDs based on step name
    f = types.NormalizeFindings(f, stepName)
    // ... further processing
}

```

## Merging User Overrides and Filtering

The pipeline supports human-in-the-loop workflows through `types.MergeUserOverrides` (lines 66-78 in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go)). When users supply custom instructions or add findings via the terminal UI, this function stamps user-contributed entries with `Source: "user"` and assigns IDs like `user-1` to distinguish them from automated detections.

The system also implements selective processing through **FilterFindings** and **ExcludeFindings**. These functions preserve the original summary unless the item count changes, in which case they recompute the summary using `summarizeSelectedFindings` to maintain accuracy.

## Decision Logic: Actionable vs. Ask-User Findings

The executor routes normalized findings through three boolean predicates to determine the next action:

- **Ask-User Detection**: `types.HasAskUserFindings` scans for findings where `Finding.actionOrDefault` returns `ActionAskUser`. This helper treats missing action values as ask-user (the safe default), ensuring uncertain findings always receive human validation.
- **Auto-Fix Extraction**: `types.AutoFixableFindings` (lines 53-62) filters for findings explicitly marked with `ActionAutoFix`, isolating candidates for automated remediation.
- **General Actionability**: `types.HasActionableFindings` returns true if any finding is not a `no-op`, distinguishing between findings requiring intervention and informational-only results.

```go
// internal/pipeline/executor.go (decision logic)
switch {
case types.HasAskUserFindings(f):
    // Park the run – TUI will prompt for manual resolution
    e.parkRun(f)
case types.HasActionableFindings(f):
    // Invoke fixer agent for auto-fixable findings
    e.runFixer(f)
default:
    // No actionable issues detected
    e.markStepSuccess()
}

```

If ask-user findings exist, the executor parks the pipeline run and presents them in the TUI for manual review. When only auto-fixable findings exist and the step permits automatic remediation, the executor triggers the fixer agent.

## Persistence and Round History

After processing, final findings—including any user edits—persist to the database as JSON in `FindingsJSON` and `UserFindingsJSON` columns. The [`internal/pipeline/steps/round_history.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/round_history.go) file handles this persistence, storing round-level findings for UI rendering and historical audit trails. This storage pattern enables the round-history view, allowing users to trace how findings evolved across pipeline executions.

## Summary

- **StepOutcome** carries JSON-encoded findings from individual steps (test, lint, review) to the central executor.
- **ParseFindingsJSON** and **NormalizeFindings** convert wire formats and assign deterministic IDs like `<step>-<n>`.
- **MergeUserOverrides** incorporates human contributions with `Source: "user"` tagging.
- **HasAskUserFindings** and **AutoFixableFindings** predicates route findings to human review, auto-fix, or success states based on action metadata.
- **Round history** persists processed findings to the database for auditability and UI rendering.

## Frequently Asked Questions

### How does no-mistakes distinguish between user-added and automated findings?

The `types.MergeUserOverrides` function in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) automatically assigns `Source: "user"` to any findings added through custom instructions or the UI, while automated step findings retain their original source identification. This distinction allows the UI to render user contributions differently and ensures user overrides take precedence during conflict resolution.

### What happens when a pipeline step produces findings without explicit action IDs?

The `Finding.actionOrDefault` helper treats missing or unspecified action fields as `ActionAskUser` as a safe default. This ensures that any finding with unclear remediation requirements automatically triggers human review rather than risking unintended auto-fixes.

### Can findings be filtered or excluded before processing?

Yes. The `types.FilterFindings` and `types.ExcludeFindings` functions in [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) allow the executor to retain only specific finding subsets or drop selected items before running actionability predicates. These functions preserve the original summary when possible or recompute it using `summarizeSelectedFindings` when the item count changes.

### Where does the pipeline store findings after step completion?

The [`internal/pipeline/steps/round_history.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/round_history.go) file persists final findings to the database as JSON strings in `FindingsJSON` and `UserFindingsJSON` fields. This storage supports the round-history view in the terminal UI and maintains an audit trail of what the pipeline detected and how it was resolved.