# How Apache Maka Creates an Immutable Run Composition Snapshot

> Learn how Apache Maka's Run Composer creates immutable snapshots. Discover how Object.freeze ensures deterministic replay across restarts for your system prompt and source revisions.

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

---

**Apache Maka's Run Composer generates an immutable Run Composition snapshot by freezing the system prompt text and source revision identifiers using `Object.freeze`, ensuring deterministic replay across process restarts.**

Apache Maka is an open-source framework for building reliable AI runtime hosts. The **Run Composition snapshot** captures the exact state of model inputs for a single turn, guaranteeing that restarts or replays produce identical results without re-evaluating dynamic inputs.

## Core Components of the Snapshot

Every immutable snapshot consists of two frozen artifacts:

- **System Prompt Text** – The complete prompt that the model receives, assembled from skill catalogs, workspace instructions, and plan-mode text.
- **Source Revision Identifiers** – An immutable list tracking the exact runtime-policy, memory-bundle, memory, and skill-catalog revisions used to construct the prompt.

Both components are sealed with `Object.freeze`, making them non-configurable and non-writable once created.

## How the Snapshot is Assembled

The assembly process follows a strict pipeline defined in [`packages/runtime-host/src/server/interactive-run-composer.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/server/interactive-run-composer.ts).

### Collecting Tools and Capabilities

The `createInteractiveRunComposer` function (lines 45–86) initializes the composer by building the final tool list and determining whether a tool-availability policy is required for the session. This establishes the operational boundaries for the upcoming turn.

### Caching Per-Turn Prompts

To ensure immutability across repeated access, the system maintains a `resolvedSystemPrompts` cache (lines 100–112). This Map stores `Promise<ResolvedRunPrompt>` instances keyed by the composite string `<sessionId>\0<turnId>`. Subsequent requests for the same session and turn return the identical cached promise, preventing reconstruction and potential mutation.

### Reading Prompt State

The `readPromptState` function (lines 558–669) gathers current revision data from three sources:

1. **Runtime Policy** – The active execution constraints and capabilities.
2. **Memory Bundle** – The consolidated memory state for the session.
3. **Memory Revision** – Skipped for child-instruction runs to maintain context isolation.

These values represent the *mutable* inputs that get captured into the immutable snapshot.

### Building and Freezing the Prompt Text

At lines 202–262, `resolveSystemPrompt` composes the final system prompt by aggregating:

- Skill catalog definitions
- Workspace-specific instructions
- Plan-mode contextual text
- Dynamic provider options

Once assembled, the function applies `Object.freeze` to the result, creating an immutable prompt object that cannot be altered by downstream consumers.

### Creating the Revision List

The `interactiveSourceRevisions` function (lines 442–456) returns an immutable array of `RunCompositionSourceRevision` objects. Each entry records the exact revision hash or identifier for every component used during prompt construction, establishing a complete provenance chain.

### Exporting the Frozen Composer

The final `HostRunComposer` object (lines 274–284) exposes a frozen interface containing:

- `composerId` and `composerRevision` identifiers
- The tool list and availability policy
- `resolveSystemPrompt` – The frozen prompt factory
- `turnTailPrompt` – Any additional frozen context

According to the architecture documentation in [`docs/architecture/runtime-host-architecture.md`](https://github.com/apache/maka/blob/main/docs/architecture/runtime-host-architecture.md), this design "freezes the model-visible basis for one Run: base system prompt, tool catalog, tool availability policy, base provider options, and the revisions of inputs used to construct them."

## Immutability Mechanisms

The snapshot achieves true immutability through several defensive programming techniques.

**Single Construction Point** – The snapshot builds exactly once per turn during the initial `resolveSystemPrompt` call. All subsequent accesses hit the cached frozen object.

**JavaScript Object Freezing** – The implementation uses `Object.freeze` extensively. This native JavaScript method prevents extensions, deletions, and value modifications to objects and arrays, throwing errors in strict mode if mutation attempts occur.

**Durable Store Persistence** – The frozen snapshot serializes into the Durable Store, allowing a restarted Runtime Host to reload the exact composition without re-executing the construction logic or re-querying volatile data sources.

## Practical Implementation

### Creating a Composer and Capturing a Snapshot

```typescript
import { createInteractiveRunComposerFactory } from '@maka/runtime-host';
import { readRuntimePolicy } from '@maka/core/runtime-policy';
import { memoryCoordinator } from '@maka/runtime-host';

// Initialize the factory once per Runtime Host
const factory = createInteractiveRunComposerFactory({
  clientCapabilities: myCapabilityCoordinator,
  resolveTavilyWebSearchReadiness: async () => false,
  skills: mySkillCatalog,
  memory: memoryCoordinator,
  taskLedger: myTaskLedger,
});

// Instantiate composer for a specific backend context
const composer = await factory({
  backendContext: myBackendContext,
  connection: undefined,
  modelId: 'gpt-4o',
  runtimePolicy: await readRuntimePolicy(),
  contextWindow: null,
});

// Generate the immutable snapshot
const promptSnapshot = await composer.resolveSystemPrompt({
  sessionId: 'sess-123',
  turnId: 'turn-1',
  cwd: '/path/to/project',
});

// Both properties are frozen
console.log(promptSnapshot.text);            // Immutable system prompt
console.log(promptSnapshot.sourceRevisions); // Immutable revision list

```

### Verifying Snapshot Immutability

```typescript
// Subsequent calls return the identical frozen object
const cachedSnapshot = await composer.resolveSystemPrompt({
  sessionId: 'sess-123',
  turnId: 'turn-1',
  cwd: '/path/to/project',
});

console.log(cachedSnapshot === promptSnapshot); // true

```

The referential equality proves that the system returns the cached frozen instance rather than reconstructing the object, ensuring consistent model inputs across the entire session lifecycle.

## Summary

- Apache Maka's **Run Composer** constructs snapshots in [`packages/runtime-host/src/server/interactive-run-composer.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/server/interactive-run-composer.ts) by freezing prompt text and revision metadata.
- The **cache mechanism** uses `<sessionId>\0<turnId>` keys to ensure single construction and consistent retrieval.
- **`Object.freeze`** makes both the prompt content and source revision arrays immutable at the JavaScript engine level.
- **Durable Store** persistence enables exact replay after process restarts without re-evaluating dynamic inputs.
- The architecture guarantees that models receive identical prompts during replays, session restores, or distributed execution scenarios.

## Frequently Asked Questions

### How does the Run Composer prevent accidental mutation of cached prompts?

The implementation wraps all snapshot data with `Object.freeze` immediately after construction in the `resolveSystemPrompt` function. This prevents any code from adding, deleting, or changing properties on the prompt object or its source revision array. Additionally, the caching layer in `resolvedSystemPrompts` stores the frozen promise, ensuring that every consumer receives the exact same object instance.

### What specific source revisions are tracked in the snapshot?

The snapshot captures four critical revision identifiers: the **runtime-policy** version that governed execution constraints, the **memory-bundle** state aggregating session context, the individual **memory** revision for persistence tracking, and the **skill-catalog** version defining available tools. These are stored as `RunCompositionSourceRevision` objects in a frozen array returned by `interactiveSourceRevisions` at lines 442–456.

### Can the immutable snapshot be used across different Runtime Host processes?

Yes. The frozen snapshot serializes into the Durable Store, which persists beyond individual process lifetimes. When a Runtime Host restarts, it reloads the exact same composition from storage rather than reconstructing it from mutable sources. This guarantees that distributed or recovered executions operate on identical model inputs.

### Where does the caching logic reside in the source code?

The per-turn caching mechanism resides in [`interactive-run-composer.ts`](https://github.com/apache/maka/blob/main/interactive-run-composer.ts) between lines 100–112. The `resolvedSystemPrompts` Map maintains weak references to frozen promises keyed by session and turn identifiers, ensuring that repeated access within the same turn returns the immutable snapshot without re-executing the expensive prompt resolution logic.