# How LoopXTurnRoute and LoopXTurnResultKind Enums Distinguish Turn Decisions from Prose Shorthand in LoopX

> Understand how LoopXTurnRoute and LoopXTurnResultKind enums differentiate turn decisions from prose shorthand for type-safe programmatic control and human-readable UI labels.

- Repository: [huangruiteng/loopx](https://github.com/huangruiteng/loopx)
- Tags: internals
- Published: 2026-09-02

---

**LoopXTurnRoute determines what action the Turn engine should execute next, while LoopXTurnResultKind describes the semantic outcome of a finished Turn, with prose shorthand providing human-readable labels for UI layers while the enums ensure type-safe programmatic control flow.**

LoopX implements a rigorous type system to manage the lifecycle of autonomous agent Turns through two specialized enumerations. The **LoopXTurnRoute** and **LoopXTurnResultKind** enums work in tandem to separate routing decisions from execution results, ensuring deterministic control flow while supporting human-readable logging and user interfaces.

## Understanding the Two Enum Systems

### LoopXTurnRoute: Routing the Turn Engine

**LoopXTurnRoute** determines *what* the Turn engine should do next based on envelope validation, integrity checks, and agent state. Defined in [`loopx/control_plane/turn_driver/driver.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/turn_driver/driver.py) (lines 45-52), this enum includes:

- `READY_FOR_HOST`
- `REPAIR_REQUIRED`
- `REPLAN_REQUIRED`
- `USER_ACTION_REQUIRED`
- `WAIT`
- `BLOCKED`
- `CONTRACT_ERROR`

The driver derives the route from the Turn envelope’s schema version, signature match, budget status, and the requested action type.

### LoopXTurnResultKind: Capturing Execution Outcomes

**LoopXTurnResultKind** describes *how* a Turn actually finished, serving the Turn receipt and settlement layers. This enum, defined in the Turn driver result module (typically [`loopx/control_plane/turn_driver/result.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/turn_driver/result.py)), includes:

- `VALIDATED_PROGRESS`
- `VALIDATED_COMPLETION`
- `WAIT`
- `USER_ACTION_REQUIRED`
- `HOST_FAILURE`
- `VALIDATION_FAILED`
- `WRITEBACK_FAILED`
- `QUOTA_SPEND_FAILED`
- `REPAIR_REQUIRED`
- `REPLAN_REQUIRED`

## How the Enums Work Together

The Turn lifecycle follows a strict sequence from envelope validation to execution settlement, with each enum governing a distinct phase.

### Stage 1: Envelope Validation to Route Selection

According to the implementation in [`driver.py`](https://github.com/huangruiteng/loopx/blob/main/driver.py) (lines 68-79), the driver inspects incoming Turn envelopes for contract violations. If any are detected, the route is immediately set to `CONTRACT_ERROR`. When validation succeeds, the driver examines the **effective action**:

- If the action matches replan tokens (`autonomous_replan`, `successor_replan_required`), the route becomes `REPLAN_REQUIRED`
- If the action ends with `_repair` or matches repair tokens, the route becomes `REPAIR_REQUIRED`
- If policy blocks delivery, the route is `BLOCKED`
- If the Turn requires user intervention, the route is `USER_ACTION_REQUIRED`
- For quiet no-ops, the route is `WAIT`
- Otherwise, the route defaults to `READY_FOR_HOST`

### Stage 2: Execution to Result Kind

After the host executes the chosen route, the system builds a Turn receipt. The `result_kind` field captures the semantic outcome—whether the Turn achieved validated progress, completed successfully, or encountered specific failure modes like `QUOTA_SPEND_FAILED` or `WRITEBACK_FAILED`. The settlement logic uses this value to determine whether to persist state, retry the operation, or surface an error.

## Prose Shorthand vs. Structured Decisions

The LoopX architecture maintains a strict separation between programmatic enum values and human-readable representations.

### Structured Decisions (Programmatic Layer)

The engine never relies on free-form text for control flow. All routing logic checks enum members directly—for example, comparing against `LoopXTurnRoute.READY_FOR_HOST` or `LoopXTurnResultKind.VALIDATED_PROGRESS`. This ensures deterministic, type-safe operations throughout the Turn lifecycle.

### Prose Shorthand (Presentation Layer)

Values like "wait" or "user_action_required" appear in user-facing logs and markdown renderers as human-readable representations of the underlying enum values. This separation allows UI layers to display friendly phrases while the core logic remains strictly typed and deterministic.

## Implementation in the LoopX Codebase

The following examples from the LoopX repository demonstrate how these enums function in practice.

### Routing Logic

The driver logic in [`driver.py`](https://github.com/huangruiteng/loopx/blob/main/driver.py) determines the route based on envelope state and action type:

```python

# driver.py – decide which route a Turn should take

if should_run:
    if not delivery_allowed or not must_attempt:
        route = LoopXTurnRoute.BLOCKED
    elif effective_action in REPLAN_ACTIONS:
        route = LoopXTurnRoute.REPLAN_REQUIRED
    elif effective_action in REPAIR_ACTIONS or effective_action.endswith(
        ("_repair", "_repair_required")
    ):
        route = LoopXTurnRoute.REPAIR_REQUIRED
    else:
        route = LoopXTurnRoute.READY_FOR_HOST

```

### Receipt Construction

After execution, the transaction layer builds receipts using the result kind:

```python

# transaction.py – build a receipt after the host finishes

receipt = {
    "route": {"kind": route.value},
    "result_kind": LoopXTurnResultKind.VALIDATED_PROGRESS.value,
    "payload": {...},
}

```

### Test Validation

Unit tests verify that receipts carry the correct semantic result:

```python

# test_loopx_turn_transaction.py – asserting the result kind

def test_turn_receipt_validation():
    receipt = ValidatedTurnReceipt.from_execution(execution)
    assert receipt.result_kind == LoopXTurnResultKind.VALIDATED_PROGRESS

```

## Summary

- **LoopXTurnRoute** controls what happens next in the Turn lifecycle, derived from envelope validation and action analysis in the Turn driver at [`loopx/control_plane/turn_driver/driver.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/turn_driver/driver.py)
- **LoopXTurnResultKind** records how a Turn actually executed, used by settlement logic to determine persistence and retry strategies
- The separation between routing (decision) and result (outcome) allows LoopX to handle complex agent workflows with clear state transitions
- Prose shorthand provides human-readable labels for UI components, while the enum system ensures type-safe, deterministic control flow
- Key implementation files include [`loopx/control_plane/turn_driver/driver.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/turn_driver/driver.py) for routing logic and the corresponding result module for outcome tracking

## Frequently Asked Questions

### What is the difference between LoopXTurnRoute and LoopXTurnResultKind?

**LoopXTurnRoute** determines the next action the engine should take based on the current state and envelope validation, while **LoopXTurnResultKind** describes the semantic outcome of a completed Turn. The route enum drives control flow decisions before execution, whereas the result kind enum categorizes the outcome after execution for settlement and logging purposes.

### Where are LoopXTurnRoute and LoopXTurnResultKind defined in the LoopX repository?

LoopXTurnRoute is defined in [`loopx/control_plane/turn_driver/driver.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/turn_driver/driver.py) (lines 45-52), which contains the routing logic that maps envelope states to specific route values. LoopXTurnResultKind is defined in the Turn driver result module, typically [`loopx/control_plane/turn_driver/result.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/turn_driver/result.py), where it maps execution outcomes to semantic result categories used by the settlement layer.

### How does LoopX handle user-facing messages differently from internal routing decisions?

LoopX uses prose shorthand such as "wait" or "user_action_required" for human-readable UI displays and logs, while the core engine strictly uses enum members like `LoopXTurnRoute.WAIT` or `LoopXTurnResultKind.USER_ACTION_REQUIRED` for all programmatic decisions. This ensures type safety and deterministic control flow in the engine while allowing flexible, user-friendly presentation layers.

### What triggers a REPAIR_REQUIRED or REPLAN_REQUIRED route in LoopX?

The driver sets `REPLAN_REQUIRED` when the effective action matches known replan tokens such as `autonomous_replan` or `successor_replan_required`. It sets `REPAIR_REQUIRED` when the action ends with `_repair` or matches entries in a predefined repair token list, as implemented in the routing logic of [`driver.py`](https://github.com/huangruiteng/loopx/blob/main/driver.py). These routes signal the host to initiate recovery workflows rather than normal execution.