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

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 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:

// 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.

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:

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:

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 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, 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 within the AgentRun class. Supporting type definitions exist in packages/runtime/src/types.ts, while architectural rationale appears in docs/architecture/runtime-resume-architecture.md and ARCHITECTURE.md.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →