# Apache Maka Crash Recovery: How the Runtime Resume Protocol Survives Process Failures

> Apache Maka crash recovery ensures turns survive process failures. Learn how its runtime resume protocol uses SQLite and a four-phase recovery to guarantee safe resumption.

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

---

**Apache Maka guarantees that a turn (an atomic interaction with a model) can survive a process crash and be safely resumed through a durable SQLite event log and a deterministic four-phase recovery protocol.**

This article explains how Apache Maka implements crash recovery based on the runtime architecture documented in `apache/maka`. The design centers on an append-only **RuntimeEventStore**, a **RecoveryResolver** decision engine, and layered resume phases that range from basic safety checks to full side-effect reconciliation.

---

## Core Components of Apache Maka Crash Recovery

Apache Maka's crash recovery system relies on three interconnected components that ensure deterministic, fail-closed behavior after unexpected termination.

### RuntimeEventStore: The Durable Source of Truth

The **RuntimeEventStore** is a SQLite-backed append-only log (`runtime.sqlite`) that records every `RuntimeEvent` produced by the Runtime Host. It serves as the *single source of truth* for all recovery decisions.

Key characteristics of the store:

- **Atomic commits** — events are written transactionally before any acknowledgment to the model
- **Prefix projection** — recovery reads only the *committed prefix* of events, ignoring uncommitted writes
- **Immutable history** — once committed, events are never modified or deleted

The store implementation lives in [`packages/runtime/src/runtime-event-store.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/runtime-event-store.ts). During normal operation, it receives events from the Runtime Host through the SessionManager → AgentRun pipeline. After a crash, a new store instance opens the same SQLite file to begin recovery.

### Crash Contract (Phase 0): The Safety Gate

The **Phase 0 Crash Contract** defines what can be safely replayed after a crash. This contract, documented in [`docs/architecture/runtime-resume-phase0-crash-contract.md`](https://github.com/apache/maka/blob/main/docs/architecture/runtime-resume-phase0-crash-contract.md), inspects the committed event prefix and produces a deterministic `ResumePlan`.

The contract applies a simple but critical rule:

- **Safe replay** — permitted if the committed prefix ends *before* any tool operation (`before_function_call`, `after_function_call`, etc.)
- **Blocked** — required if any tool operation appears in the prefix, since side effects may have occurred

This fail-closed design ensures Maka never guesses about unknown states. If the contract cannot verify safety, it blocks automatic resumption.

### RecoveryResolver: The Authoritative Decision Engine

The **RecoveryResolver** implements the complete decision logic across all recovery phases. Located in [`packages/runtime/src/recovery-resolver.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/recovery-resolver.ts), it:

- Reads the committed prefix from RuntimeEventStore
- Applies the Phase 0-3 contract rules
- Emits deterministic decisions: `completed`, `indeterminate`, `corruption`, `safe_replay`, or `blocked`

The RecoveryResolver **never guesses**. Unknown states are treated as failures, forcing manual intervention rather than risking incorrect replay. The architectural decision record in [`docs/architecture/runtime-recovery-resolver-adr.zh-CN.md`](https://github.com/apache/maka/blob/main/docs/architecture/runtime-recovery-resolver-adr.zh-CN.md) documents this fail-closed philosophy.

---

## The Four-Phase Runtime Resume Architecture

Maka structures crash recovery across four phases, with each phase adding capabilities while maintaining safety guarantees.

| Phase | Purpose | Safety Guarantee |
|-------|---------|----------------|
| **Phase 0 — Crash Contract** | Determine if prefix is replay-safe | No tool side-effects replayed; deterministic safe/blocked decision |
| **Phase 1 — Safe Boundary** | Enable automatic resumption for Desktop/CLI | Safe replay without manual intervention when contract permits |
| **Phase 2 — Tool Boundary (T1/T2)** | Capture tool execution state atomically | Tool dispatch events mark boundaries; journal is projection of event store |
| **Phase 3 — Full Recovery** | Side-effect reconciliation and continuation runs | Complete fail-closed recovery with idempotent re-execution |

Only Phases 0 and 1 are required for basic crash-only safety. Phases 2 and 3 add sophistication for complex scenarios involving tool side effects and multi-turn continuations.

The system architecture flows from **Runtime Host → SessionManager → AgentRun → RuntimeEventStore**, with recovery traversing this path in reverse through the RecoveryResolver.

---

## Enabling Automatic Safe-Boundary Resume

Apache Maka supports optional automatic crash recovery through an environment flag. When enabled, the Runtime Host queries the RecoveryResolver and automatically continues safe turns.

```bash

# Enable safe-boundary resume for Desktop or CLI

export MAKA_RUNTIME_SAFE_BOUNDARY_RESUME=1

```

With this flag active:

1. The Runtime Host opens the workspace's RuntimeEventStore
2. Invokes RecoveryResolver.computeResumePlan()
3. If the plan is `safe_replay`, automatically re-executes the model turn
4. If `blocked`, presents a manual "Resume" option in the UI or CLI diagnostic

Without the flag, all blocked turns require explicit user action.

---

## Crash Recovery in Practice: A Step-by-Step Walkthrough

When a process terminates unexpectedly, Apache Maka follows this deterministic sequence:

1. **Crash occurs** — process receives `SIGKILL` or equivalent; SQLite file contains committed event prefix

2. **Workspace reopened** — new RuntimeEventStore instance opens `runtime.sqlite` from the workspace

3. **Prefix projection** — store identifies the last fully committed sequence of events

4. **ResumePlan generation** — RecoveryResolver applies Phase 0 contract rules:
   - Ends before `before_function_call`? → `safe_replay`
   - Contains any tool boundary event? → `blocked`

5. **Safe replay execution** — for `safe_replay`, Runtime Host re-executes from last model turn using recorded messages; no tool code runs

6. **Blocked handling** — for `blocked`, UI shows Resume button or CLI emits diagnostic; user chooses retry, edit, or abort

Throughout this process, the durable ledger remains **read-only** during decision-making. No mutations occur until a definitive safe replay is confirmed.

---

## Code Example: Querying Recovery State

The following TypeScript demonstrates how applications can integrate crash recovery detection:

```typescript
// Enable safe-boundary resume (optional)
process.env.MAKA_RUNTIME_SAFE_BOUNDARY_RESUME = '1';

import { RuntimeEventStore, RecoveryResolver } from '@maka/runtime';

async function evaluateCrashRecovery(workspacePath: string): Promise<string> {
  const store = await RuntimeEventStore.open(workspacePath);
  const resolver = new RecoveryResolver(store);
  
  // Returns 'safe_replay' | 'blocked' | 'completed' | 'indeterminate' | 'corruption'
  const plan = await resolver.computeResumePlan();
  return plan;
}

// CLI integration example
(async () => {
  const workspace = process.argv[2] || '/path/to/workspace';
  const plan = await evaluateCrashRecovery(workspace);
  
  switch (plan) {
    case 'safe_replay':
      console.log('✅ Crash recovery: safe to resume automatically');
      // RuntimeHost.resumeTurn(workspace) replays model turn
      break;
    case 'blocked':
      console.warn('⚠️ Crash recovery: manual intervention required');
      process.exitCode = 1;
      break;
    case 'completed':
      console.log('Turn already completed, no recovery needed');
      break;
    default:
      console.error(`❌ Recovery failed: ${plan}`);
      process.exitCode = 2;
  }
})();

```

The `RecoveryResolver` class encapsulates all phase transitions, ensuring consistent behavior across Desktop, CLI, and embedded deployments.

---

## Source Files for Apache Maka Crash Recovery

| Path | Description |
|------|-------------|
| [`docs/architecture/runtime-resume-phase0-crash-contract.md`](https://github.com/apache/maka/blob/main/docs/architecture/runtime-resume-phase0-crash-contract.md) | Formal contract defining safe-replay vs. blocked outcomes |
| [`docs/architecture/runtime-recovery-resolver-adr.zh-CN.md`](https://github.com/apache/maka/blob/main/docs/architecture/runtime-recovery-resolver-adr.zh-CN.md) | Architectural decision record for the RecoveryResolver |
| [`packages/runtime/src/runtime-event-store.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/runtime-event-store.ts) | SQLite-backed durable event log implementation |
| [`packages/runtime/src/recovery-resolver.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/recovery-resolver.ts) | Recovery decision engine with Phase 0-3 logic |
| [`README.md`](https://github.com/apache/maka/blob/main/README.md) (Local Data and Recovery section) | Feature overview and environment flag documentation |
| [`ARCHITECTURE.md`](https://github.com/apache/maka/blob/main/ARCHITECTURE.md) | System-wide architecture with Runtime Resume component placement |

---

## Summary

- **Apache Maka crash recovery** depends on an append-only SQLite **RuntimeEventStore** as the single source of truth
- The **Phase 0 Crash Contract** deterministically classifies crashes as `safe_replay` or `blocked` based on whether tool operations appear in the committed prefix
- The **RecoveryResolver** implements fail-closed decision logic across four phases, never guessing about unknown states
- **Safe-boundary resume** can be enabled via `MAKA_RUNTIME_SAFE_BOUNDARY_RESUME=1` for automatic recovery in Desktop and CLI environments
- All recovery operations are read-only until safety is confirmed, preserving ledger integrity

---

## Frequently Asked Questions

### What happens if Apache Maka crashes during a tool execution?

If the committed event prefix contains any tool boundary event (`before_function_call`, `after_function_call`, or `after_function_response`), the **Phase 0 Crash Contract** returns `blocked`. The turn cannot be automatically resumed because side effects may have occurred. The user must manually decide whether to retry, edit, or abort the turn.

### How does Apache Maka ensure the event log isn't corrupted during a crash?

The **RuntimeEventStore** uses SQLite's atomic transaction guarantees. Events are committed to disk before any acknowledgment returns to the Runtime Host. During recovery, only the *committed prefix* is read—partial writes in the WAL or journal files are excluded by the prefix projection logic in [`runtime-event-store.ts`](https://github.com/apache/maka/blob/main/runtime-event-store.ts).

### Can I disable automatic crash recovery in Apache Maka?

Yes. Automatic safe-boundary resume is **opt-in** via the `MAKA_RUNTIME_SAFE_BOUNDARY_RESUME` environment variable. Without this flag, all turns that would qualify for `safe_replay` still require explicit user confirmation through the UI or CLI, matching the behavior of `blocked` turns.

### What is the difference between Phase 1 and Phase 3 recovery?

**Phase 1 (Safe Boundary)** enables automatic resumption when the Phase 0 contract returns `safe_replay`—essentially crashes that occurred before any tool execution. **Phase 3 (Full Recovery)** handles complex scenarios with tool side effects through the complete `RecoveryResolver` decision table, including `tool_recovery_decided` events and continuation-run manifests for multi-turn recovery.