# Critical Invariant for a Terminal Run in Apache Maka: Event Log Immutability

> Discover the critical invariant for a terminal Apache Maka Run event log immutability. Learn how this ensures deterministic crash recovery and race-free downstream consumption.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: internals
- Published: 2026-08-26

---

**Once an Apache Maka Run enters a terminal state—completed, failed, or canceled—its event log becomes permanently immutable and its status can never change again, ensuring deterministic crash recovery and race-free downstream consumption.**

Apache Maka manages long-running agent workflows through the `AgentRun` abstraction defined in the `apache/maka` repository. The **critical invariant for a terminal Run** guarantees that upon reaching a final state, all mutation operations cease, creating a stable snapshot that recovery logic, UI components, and analytics pipelines can trust implicitly.

## What Constitutes a Terminal Run

In Maka's runtime model, a Run represents the execution lifecycle of an agent session. A Run becomes **terminal** when it reaches one of three final statuses:

- **completed**: The agent finished successfully
- **failed**: The agent encountered an unrecoverable error  
- **canceled**: The user or system aborted the execution

Once in any of these states, the Run exits the active execution pool and enters a frozen, immutable condition.

## The Immutability Invariant Explained

The critical invariant is formally defined as:

> **Once a Run becomes terminal, its event log is immutable; no further events may be appended, and the Run’s status never changes again.**

This invariant is enforced in [`packages/runtime/src/agent-run.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run.ts) within the `AgentRun` class implementation. The `isTerminal()` method serves as the gatekeeper for all mutation operations, checking whether `this.status` has diverged from the initial `'running'` state.

### Enforcement in the Runtime

The `AgentRun` class maintains a private `events` array and a `status` field. When `finish()` is called to complete a Run, the implementation records the terminal event and immediately locks the instance against further modifications:

```typescript
// packages/runtime/src/agent-run.ts (conceptual implementation)

export class AgentRun {
  private readonly events: RunEvent[] = [];
  private status: RunStatus = 'running';

  public finish(finalStatus: 'completed' | 'failed' | 'canceled'): void {
    if (this.isTerminal()) {
      throw new Error('Attempted to finish an already-terminal run');
    }
    this.status = finalStatus;
    this.events.push({type: 'terminal', status: finalStatus, timestamp: Date.now()});
  }

  public isTerminal(): boolean {
    return this.status !== 'running';
  }

  public addEvent(event: RunEvent): void {
    if (this.isTerminal()) {
      throw new Error('Cannot add events to a terminal Run');
    }
    this.events.push(event);
  }
}

```

Any attempt to invoke `addEvent()` after the Run has terminated triggers an explicit error, preventing invariant violations that could corrupt the event stream.

## Why the Invariant Matters for System Reliability

The terminal Run invariant provides foundational guarantees for three critical subsystems:

### Crash Recovery and Deterministic Replay

When the host process restarts, Maka's recovery logic replays the event log from durable storage up to the terminal event. Because the log cannot change after termination, the reconstructed state is deterministic and consistent across all recovery attempts. This immutability eliminates the risk of split-brain scenarios or state divergence during resume operations, as documented in [`docs/architecture/runtime-resume-architecture.md`](https://github.com/apache/maka/blob/main/docs/architecture/runtime-resume-architecture.md).

### Concurrent UI Consistency

The UI may query Run status at any frequency without locking mechanisms. Knowing that a terminal Run will never emit new events eliminates race conditions between the runtime and rendering threads. This allows the frontend to cache terminal Run states indefinitely without polling for changes.

### Analytics and Auditability

Metrics aggregation and audit logging depend on the guarantee that a terminal Run's outcome is final. Data pipelines can safely archive or delete Run metadata knowing the state will never revert or append new critical events.

## Checking Terminal State in Application Code

Client applications interacting with the Maka runtime can verify terminal status before performing operations:

```typescript
import {AgentRun} from '@maka/runtime';

const run = new AgentRun();

// ... execute agent logic ...

if (run.isTerminal()) {
  console.log('Run is finished – state is immutable and safe for archival.');
  // Safe to query final metrics without synchronization concerns
}

```

This pattern prevents applications from attempting operations on completed workflows and respects the underlying invariant.

## Key Source Files

The terminal Run invariant is implemented and documented across these locations in the **apache/maka** repository:

- **[`packages/runtime/src/agent-run.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run.ts)**: Core `AgentRun` class implementing `isTerminal()` guards and the `finish()` lifecycle method
- **[`packages/runtime/src/types.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/types.ts)**: Type definitions for `RunStatus` ('running' | 'completed' | 'failed' | 'canceled') and `RunEvent` interface  
- **[`docs/architecture/runtime-resume-architecture.md`](https://github.com/apache/maka/blob/main/docs/architecture/runtime-resume-architecture.md)**: Architecture documentation explaining how the invariant enables safe recovery and resumption of interrupted Runs
- **[`ARCHITECTURE.md`](https://github.com/apache/maka/blob/main/ARCHITECTURE.md)**: High-level system overview referencing the Runtime lifecycle and AgentRun invariants

## Summary

- **Terminal Runs** in Apache Maka are those with statuses `completed`, `failed`, or `canceled`
- The **critical invariant** guarantees that terminal Runs have immutable event logs and unchangeable status
- Enforcement occurs in [`packages/runtime/src/agent-run.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run.ts) through the `isTerminal()` method, which blocks `addEvent()` and `finish()` operations on terminated instances
- This immutability ensures **deterministic crash recovery**, **race-free UI updates**, and **reliable analytics**
- Downstream components can safely treat terminal Runs as permanent, consistent snapshots without additional synchronization

## Frequently Asked Questions

### What happens if code attempts to add an event to a terminal Run in Maka?

The `AgentRun.addEvent()` method throws an error if invoked on a terminal instance. The implementation checks `this.isTerminal()` at the entry point and rejects the operation with the message "Cannot add events to a terminal Run", preserving the immutability guarantee.

### How does the terminal Run invariant support crash recovery?

During process restart, Maka replays the event log from durable storage up to the terminal event. Because the invariant prevents any appends after termination, the replayed state is identical across all recovery attempts, ensuring deterministic reconstruction of the final application state without divergence.

### Can a terminal Run ever change status after reaching completed, failed, or canceled?

No. According to the source code in [`packages/runtime/src/agent-run.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run.ts), the `status` field is set exactly once during the `finish()` call, and subsequent attempts to modify it are blocked by the terminal state check. This forms the core of the critical invariant: terminal status is permanent and irreversible.

### Where is the terminal state logic implemented in Apache Maka?

The primary implementation resides in [`packages/runtime/src/agent-run.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/agent-run.ts) within the `AgentRun` class. Supporting type definitions exist in [`packages/runtime/src/types.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/types.ts), while architectural rationale appears in [`docs/architecture/runtime-resume-architecture.md`](https://github.com/apache/maka/blob/main/docs/architecture/runtime-resume-architecture.md) and [`ARCHITECTURE.md`](https://github.com/apache/maka/blob/main/ARCHITECTURE.md).