# Session Management in no-mistakes Review Loops: Reviewer vs Fixer Sessions

> Understand no-mistakes session management. Learn how reviewer and fixer sessions are isolated to prevent context sharing and ensure smooth review loops in code development.

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

---

**The no-mistakes pipeline isolates adversarial review from code fixes by maintaining one durable session for the reviewer role across all review passes while spinning up a separate, isolated session for the fixer role during fix-review turns, ensuring the two agent roles never share context or state.**

The `kunchenguid/no-mistakes` repository implements a strict **session management** strategy for its AI-driven review loops. According to the project's [[`AGENTS.md`](https://github.com/kunchenguid/no-mistakes/blob/main/AGENTS.md)](https://github.com/kunchenguid/no-mistakes/blob/main/AGENTS.md#review-loop-agent-sessions) documentation, the pipeline treats the **reviewer** and **fixer** as distinct agents with separate lifecycles, preventing cross-contamination of reasoning between the role that critiques code and the role that modifies it. This design ensures that the reviewer evaluates the diff *as-is* without being influenced by the fixer's rationale.

## Review Loop Session Architecture

The review loop alternates between two phases: the initial adversarial review and subsequent fix-review turns. Each phase requires a different mindset—one critical, one constructive—which is why the pipeline binds each phase to a specific agent session.

### The Reviewer Session

The **reviewer session** is a long-lived context that survives from the initial review through every full rereview of the same run. In [[`internal/db/agent_session.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/agent_session.go)](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/agent_session.go), this session is persisted with the role identifier `types.RoleReviewer`. Because this session endures across multiple passes, it retains the cumulative context of all previous review findings, but it is **strictly forbidden** from accessing the fixer's internal reasoning or the intermediate states generated during fix rounds.

### The Fixer Session

In contrast, the **fixer session** is spun up separately for the fix-review phase. Identified by `types.RoleFixer` in the database, this session operates in isolation from the reviewer. As documented in [[`AGENTS.md`](https://github.com/kunchenguid/no-mistakes/blob/main/AGENTS.md)](https://github.com/kunchenguid/no-mistakes/blob/main/AGENTS.md#review-fixer-verification-discipline) under the *Review Fixer Verification Discipline* section, the fixer must apply all suggested changes before a focused verification step, and it runs without access to the full repository test or lint suite, ensuring the fixes are generated in a clean environment.

## How Session Isolation Is Enforced

Isolation is enforced at the database layer and through executor logic in [[`internal/pipeline/sessions.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/sessions.go)](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/sessions.go). The pipeline uses a role-based lookup strategy to ensure that `getAgentSession` returns the correct context for the current task.

### Role-Based Session Lookup

The core dispatch logic relies on a helper function that keys sessions by both `RunID` and `AgentRole`. This guarantees that a request for the reviewer role never returns the fixer's session, even if both exist in the database.

```go
// getAgentSession retrieves or creates a session for a specific role.
// role is either types.RoleReviewer or types.RoleFixer.
func getAgentSession(ctx context.Context, db *db.DB, runID string, role types.AgentRole) (*db.AgentSession, error) {
    // Attempt to fetch an existing session for this run and role.
    sess, err := db.AgentSession.FindByRunAndRole(ctx, runID, role)
    if err == nil && sess != nil {
        return sess, nil // reuse existing session
    }

    // No session exists—create a fresh one for this role.
    newSess := &db.AgentSession{
        RunID: runID,
        Role:  role,
        // The underlying LLM agent (e.g., Codex, Claude) is instantiated here.
    }
    if err := db.AgentSession.Insert(ctx, newSess); err != nil {
        return nil, err
    }
    return newSess, nil
}

```

When the executor runs a review step, it calls `getAgentSession` with `types.RoleReviewer`. During fix-review turns, it calls the same function but passes `types.RoleFixer`, triggering the creation or retrieval of a completely separate session object.

### Cold Start Configuration

The pipeline respects a `session_reuse` configuration flag defined in the executor settings. When `session_reuse: false` is set, the system bypasses the lookup logic and forces a **cold start** for every step, instantiating a fresh agent even if a durable session exists in the database. This flag is useful for debugging or when strict reproducibility is required, as it eliminates any hidden state carried over from previous turns.

## Database Schema and Persistence

Session metadata is stored in [[`internal/db/agent_session.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/agent_session.go)](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/agent_session.go), where the `AgentSession` table is keyed by a composite of `RunID` and `Role`. This schema ensures that:

- **Reviewer** and **fixer** contexts are stored in separate rows.
- Crash recovery is possible by reloading the correct session based on the current run state and intended role.
- Sessions are safely discarded when a run completes, preventing leakage between independent runs.

## Implementation in the Codebase

The executor functions in [[`internal/pipeline/sessions.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/sessions.go)](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/sessions.go) demonstrate the practical application of the session management logic. The following snippets illustrate how the pipeline switches contexts between review and fix operations.

```go
// runReviewStep executes the adversarial review using the reviewer session.
func runReviewStep(ctx context.Context, exec *Executor) error {
    sess, err := getAgentSession(ctx, exec.DB, exec.Run.ID, types.RoleReviewer)
    if err != nil {
        return err
    }
    // Invoke the LLM via the reviewer session.
    findings, err := sess.Agent.Review(ctx, exec.Diff)
    if err != nil {
        return err
    }
    // Store findings for the fixer phase...
    return nil
}

// runFixReviewStep executes the fix-review turn using the isolated fixer session.
func runFixReviewStep(ctx context.Context, exec *Executor) error {
    sess, err := getAgentSession(ctx, exec.DB, exec.Run.ID, types.RoleFixer)
    if err != nil {
        return err
    }
    // The fixer receives the diff and findings, but operates in its own context.
    fixes, err := sess.Agent.Fix(ctx, exec.Diff, exec.Findings)
    if err != nil {
        return err
    }
    // Apply fixes to the working tree...
    return nil
}

```

These functions demonstrate that while the same `getAgentSession` helper is used, the **`role` parameter** ensures complete isolation between the critical reviewer and the constructive fixer.

## Summary

- **no-mistakes** maintains **one durable reviewer session** across all review passes in a run, ensuring cumulative context for adversarial analysis.
- A **separate fixer session** is created for fix-review turns, preventing the reviewer from inheriting the fixer's reasoning.
- Session isolation is enforced through **role-based database keys** (`RunID` + `Role`) in [`internal/db/agent_session.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/agent_session.go).
- The `session_reuse` flag can force **cold starts** (`session_reuse: false`), discarding all state for maximum reproducibility.
- Executor logic in [`internal/pipeline/sessions.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/sessions.go) retrieves the correct session via `getAgentSession`, guaranteeing that roles never share a session context.

## Frequently Asked Questions

### Why must reviewer and fixer sessions remain separate?

Separating the sessions ensures that the reviewer evaluates the code **as-is** without being influenced by the fixer's rationale or intermediate changes. This maintains the integrity of the adversarial review process, as implemented in `kunchenguid/no-mistakes` according to the [`AGENTS.md`](https://github.com/kunchenguid/no-mistakes/blob/main/AGENTS.md) specification.

### What happens when session_reuse is set to false?

When `session_reuse: false` is configured, the pipeline forces a **cold start** for every step. The `getAgentSession` function creates a fresh agent instance regardless of whether a previous session exists in the database, eliminating any hidden state from prior turns.

### How does the pipeline recover sessions after a crash?

The pipeline recovers by querying [`internal/db/agent_session.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/agent_session.go) using the composite key of `RunID` and `Role`. Since reviewer and fixer sessions are stored in separate rows, the executor can reload the exact context needed to resume the review loop without cross-contamination.

### Can the same agent instance be used for both roles?

No. The codebase explicitly forbids sharing agent instances between roles. The `getAgentSession` function requires a distinct `AgentRole` argument (`RoleReviewer` or `RoleFixer`), and the database schema enforces this separation by persisting sessions with role-specific identifiers.