# Gate Context Classifier for Recursive Pipeline Containment in No-Mistakes

> Understand the gate context classifier in no-mistakes. This mechanism prevents recursive pipeline execution by verifying gate-directory identity and IPC peer ancestry for secure access control.

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

---

**The gate context classifier in `internal/gatecontext` is an authoritative access control mechanism that prevents recursive pipeline execution by verifying both gate-directory identity and IPC peer ancestry before allowing any step to enter the protected worktree.**

The **no-mistakes** repository implements a hardened execution environment where pipeline steps must never recursively invoke themselves within the protected gate worktree. The **gate context classifier for recursive pipeline containment** serves as the single source of truth for determining caller eligibility, ensuring that critical safety mechanisms—such as credential redaction and run-record integrity—remain uncompromised by nested execution.

## How the Gate Context Classifier Enforces Recursive Pipeline Containment

Located in [`internal/gatecontext/classifier.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/gatecontext/classifier.go), the classifier acts as the sole authority for recursive pipeline containment. Its primary responsibility is to block a pipeline step from launching another step that would re-enter the gate or daemon context. The implementation combines two independent cryptographic and filesystem signals to render its verdict.

### Canonical Gate Directory Identity

The classifier verifies that the current working directory belongs to the **canonical gate directory** registered in the database—the exact path created by `no-mistakes init`. The `gatecontext.Inspector` struct queries the database (`DB`) and path utilities (`Paths`) to confirm the caller resides within the legitimate gate worktree. If the path check fails, the classifier issues an immediate refusal.

### Daemon Peer Ancestry Verification

Even with a valid directory, the classifier requires proof of lineage. It inspects the **IPC peer ancestry** via the `PeerPID` field in `gatecontext.Request`, walking the process chain to verify the caller is a direct child or descendant of the daemon that owns the gate. This prevents external processes from spoofing location while lacking the proper daemon parentage.

### Refusal Result Handling

When either signal is missing, the classifier returns a `gatecontext.Result` whose `ErrorCode` identifies the refusal type. Callers invoke `gatecontext.RefusalMessage(result)` to generate a clear abort message, ensuring recursive attempts fail fast with actionable diagnostics.

## Protected Entry Points in the No-Mistakes Pipeline

Every component capable of initiating a pipeline step must consult the classifier before proceeding. This universal enforcement guarantees that **recursive pipelines are impossible** regardless of entry vector.

- **CLI pre-flight** – Before executing any `axi` or `no-mistakes` command, `classifyGateControlCaller` in [`internal/cli/gate_context.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/gate_context.go) invokes the inspector to validate context.

- **Daemon mutation ingress** – The daemon’s `gateContextResult` handler in [`internal/cli/daemon_cmd.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/daemon_cmd.go) classifies the caller before accepting mutation requests, preventing direct circumvention.

- **Branch-sync operations** – [`internal/branchsync/sync.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/branchsync/sync.go) validates gate context before modifying the protected worktree, ensuring background sync tasks cannot accidentally recurse.

- **Managed pre-receive hooks** – Server-side hooks employ the same `gatecontext.Inspector` to block direct pushes that would bypass the gate’s safety envelope.

## Code Implementation and Usage Examples

### Inspecting the Caller Context

The following pattern demonstrates how entry points instantiate the classifier and interpret results:

```go
// Create an inspector with the DB and path utilities.
inspector := gatecontext.Inspector{DB: db, Paths: paths}

// Build a request describing the current context.
req := gatecontext.Request{
    CWD:          cwd,                     // current working directory
    MarkerPresent: gatecontext.MarkerPresent(), // optional debug marker
    PeerPID:      os.Getpid(),             // PID of the calling process
}

// Perform the inspection.
result, err := inspector.Inspect(context.Background(), req)
if err != nil {
    return fmt.Errorf("gate classification failed: %w", err)
}
if result.Refused() {
    return fmt.Errorf("pipeline step refused: %s", gatecontext.RefusalMessage(result))
}

```

*Source*: [`internal/gatecontext/classifier.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/gatecontext/classifier.go)

### CLI Pre-flight Integration

The CLI wrapper encapsulates inspection logic for command-line invocations:

```go
func classifyGateControlCaller(ctx context.Context) (gatecontext.Result, error) {
    // Resolve cwd and paths…
    // …
    marker := gatecontext.MarkerPresent()
    return (gatecontext.Inspector{DB: database, Paths: p}).Inspect(
        ctx,
        gatecontext.Request{CWD: cwd, MarkerPresent: marker},
    )
}

```

*Source*: [`internal/cli/gate_context.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/gate_context.go)

### Daemon Refusal Emission

When the daemon rejects a request, it emits standardized error output:

```go
func emitGateContextRefusal(cmd *cobra.Command, result gatecontext.Result) error {
    return cmd.ErrOrStderr().Write([]byte(
        fmt.Sprintf("%s (code=%s)\n", gatecontext.RefusalMessage(result), gatecontext.ErrorCode),
    ))
}

```

*Source*: [`internal/cli/gate_context.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/cli/gate_context.go)

## Summary

- The **gate context classifier** lives in [`internal/gatecontext/classifier.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/gatecontext/classifier.go) and serves as the exclusive authority for recursive pipeline containment.
- Access requires dual verification: **canonical gate-directory identity** (database-registered path) and **daemon peer ancestry** (verified via `PeerPID` chain walking).
- All execution vectors—CLI, daemon ingress, branch-sync, and pre-receive hooks—consult the classifier before permitting mutations.
- Refusal results propagate consistent error codes through `gatecontext.ErrorCode` and human-readable messages via `gatecontext.RefusalMessage()`, ensuring uniform handling across layers.

## Frequently Asked Questions

### What happens when a recursive pipeline is detected?

The classifier returns a refusal result populated with `gatecontext.ErrorCode`, causing the caller to abort immediately with a descriptive message from `gatecontext.RefusalMessage()`. This hard stop prevents the nested step from entering the gate and subverting safety checks like credential redaction.

### How does the classifier distinguish legitimate calls from recursive ones?

It mandates two independent signals: the process must reside in the **canonical gate directory** registered in the database, and its process hierarchy—verified through `PeerPID`—must descend from the owning daemon. Possession of only one signal results in automatic refusal.

### Is the marker file used for security decisions?

No. The `gatecontext.MarkerPresent()` function serves strictly as a **diagnostic debugging aid**. The actual authorization decision relies exclusively on database-registered paths and OS-authenticated peer ancestry checks performed by `gatecontext.Inspector`.

### Where is the recursive containment logic tested?

Regression tests such as `TestGateStepCannotStartRecursivePipeline` validate that the classifier correctly rejects recursive attempts. The single-source-of-truth design in [`internal/gatecontext/classifier.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/gatecontext/classifier.go) ensures any logic drift is caught immediately by the test suite.