# How the Combined Document Lint Housekeeping Pass Optimizes Agent Invocations

> Optimize agent invocations with the combined document lint housekeeping pass. Reduce agent calls to one per change, eliminating cold starts for efficient code review.

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

---

**The combined document lint housekeeping pass eliminates an extra cold agent invocation by merging lint duties into the document step when no deterministic lint command is configured, reducing total agent calls from two to one per change.**

The `no-mistakes` pipeline orchestrates automated code maintenance through specialized agent invocations. When a repository lacks a deterministic lint command, the system executes a **combined document lint housekeeping pass** that consolidates documentation updates and lint fixes into a single agent run, cutting the overhead of cold starts in half.

## How the Optimization Works

The optimization triggers when `commands.lint` remains empty in the pipeline configuration. Instead of spawning separate agents for documentation and linting, the `DocumentStep` absorbs both responsibilities.

### Detection and State Initialization

In [`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go), the step first detects whether it should run in combined mode. At line 100, the code checks `combinedLint := sctx.Config.Commands.Lint == ""`. When this evaluates to true, the step clears any previous lint state by calling `sctx.Shared.ClearHousekeepingLint()` at line 102, ensuring a fresh execution context for the current change.

### Constructing the Unified Prompt

The `buildPrompt` method appends the `housekeepingLintSection` text (lines 49-60) to the agent prompt when `combinedLint` is enabled. This extended prompt instructs the agent to process both documentation updates and lint fixes simultaneously. The agent runs with the `housekeepingFindingsSchema` JSON schema (line 127), which structures output for both operation types under the unified purpose `"housekeeping"`.

### Splitting and Caching Results

After the agent returns, the `splitHousekeepingFindings` function (lines 92-107) separates documentation findings from lint findings based on the `category` field. The lint results are cached in the shared context via `sctx.Shared.SetHousekeepingLint` (lines 73-78), making them available to the subsequent `LintStep` without requiring a second agent invocation.

## Implementation Details and Code Paths

The core logic resides in [`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go). When configured without a lint command, the pipeline executes the following flow:

```go
// Line 100: Detect combined mode
combinedLint := sctx.Config.Commands.Lint == ""

if combinedLint {
    // Line 102: Clear previous state
    sctx.Shared.ClearHousekeepingLint()
    
    // Lines 49-60: Build prompt with lint section
    prompt := s.buildPrompt(sctx, baseSHA, ignorePatterns, combinedLint)
    
    // Line 127: Run agent once with combined schema
    result, _ := sctx.Agent.Run(ctx, agent.RunOpts{
        Prompt:     prompt,
        JSONSchema: housekeepingFindingsSchema,
        Purpose:    "housekeeping",
    })
    
    // Lines 92-107: Split and cache results
    docFindings, lintFindings := splitHousekeepingFindings(parsed)
    sctx.Shared.SetHousekeepingLint(pipeline.HousekeepingLintResult{
        FindingsJSON: types.MarshalFindingsJSON(lintFindings),
        Summary:      parsed.Summary,
    })
}

```

The `LintStep` in [`internal/pipeline/steps/lint.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/lint.go) then consumes this cached result:

```go
if lintResult := sctx.Shared.HousekeepingLint; lintResult != nil {
    // Use cached findings - no new agent call needed
    return lintResult, nil
}

```

### Key Files in the Optimization

- [`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go): Contains the detection logic, prompt construction, and result splitting.
- [`internal/pipeline/steps/lint.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/lint.go): Consumes cached lint results when available.
- [`internal/pipeline/shared.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/shared.go): Defines the `HousekeepingLintResult` structure for inter-step communication.
- [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go): Specifies the `category` field values used to route findings.

## Fail-Safe Behavior

The design incorporates a **fail-safe** mechanism that preserves correctness even when the combined pass encounters issues. If the agent cannot produce trustworthy structured output, the document step falls back to requiring human approval, and the lint step executes its own independent agent invocation. This ensures the optimization never compromises code quality while maximizing efficiency during normal operations.

## Summary

- The **combined document lint housekeeping pass** triggers when `commands.lint` is empty, merging two agent responsibilities into one invocation.
- The optimization reduces cold agent starts from two to one per change, significantly cutting initialization overhead.
- Results are split by category in `splitHousekeepingFindings` and cached via `SetHousekeepingLint` for consumption by the `LintStep`.
- Fail-safe logic ensures the pipeline falls back to separate invocations if the combined output is unreliable or malformed.
- Critical paths include [`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go) lines 100, 102, 127, and 73-78 for the core optimization logic.

## Frequently Asked Questions

### When does the combined document lint housekeeping pass activate?

The optimization activates when the pipeline configuration leaves the `commands.lint` field empty. In [`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go) at line 100, the code sets `combinedLint := sctx.Config.Commands.Lint == ""`. When this evaluates to true, the document step assumes lint duties rather than spawning a separate lint-specific agent.

### How does the LintStep access results without running its own agent?

The `LintStep` checks `sctx.Shared.HousekeepingLint` for cached results. After the combined pass runs, the `DocumentStep` stores lint findings using `SetHousekeepingLint` (lines 73-78 in document.go). The `LintStep` retrieves these findings directly from the shared context, skipping its own `Agent.Run` call entirely.

### What happens if the combined agent output is malformed?

The pipeline implements fail-safe logic that detects unreliable structured output. When the document step cannot parse valid findings, it falls back to manual approval mode and allows the `LintStep` to execute its own independent agent invocation. This guarantees linting correctness while only sacrificing the optimization benefit for edge cases.

### Which files handle the result splitting logic?

The `splitHousekeepingFindings` function in [`internal/pipeline/steps/document.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/document.go) (lines 92-107) separates documentation findings from lint findings based on the `category` field. The [`internal/types/findings.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/types/findings.go) file defines these categories, while [`internal/pipeline/shared.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/shared.go) provides the `HousekeepingLintResult` structure used to persist lint data between steps.