# Apache Maka History Compaction and Context Budget Policy Explained

> Learn about Apache Maka's history compaction and context budget policy. Understand how Maka efficiently manages conversation history with checkpoint recovery and token budgets for optimal performance.

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

---

**Apache Maka uses a two-tier system to manage conversation history: automatic history compaction with checkpoint-based recovery and per-session token budgets enforced at the UI layer.**

Maka, an open-source AI conversation platform, implements sophisticated memory management to handle unbounded chat transcripts without degrading performance. The **history compaction** mechanism archives older conversation segments while preserving reconstructability, and the **context budget policy** places hard limits on token consumption per session. Both systems are integrated across the UI (`packages/ui`) and storage (`packages/storage`) layers.

## How History Compaction Works in Maka

Maka's history compaction operates on the **long-term memory (LTM) store**, automatically reducing in-memory footprint while maintaining the ability to rebuild full conversation context when needed.

### Compaction Triggers and Checkpoints

When the storage layer receives a compaction request with `trigger = 'compaction'`, it writes a **compaction checkpoint** that marks the boundary between retained and archived history. The checkpoint ID (`compactionCheckpointId`) is stored with operation metadata, allowing subsequent reads to locate the correct history slice.

In [`packages/storage/src/sqlite-long-term-memory-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/sqlite-long-term-memory-store.ts), the compaction logic:
- Persists checkpoint references per session
- Enables incremental reconstruction of trimmed transcripts
- Coordinates with the schema defined in [`sqlite-long-term-memory-schema.ts`](https://github.com/apache/maka/blob/main/sqlite-long-term-memory-schema.ts)

### Handling Compaction Failures

Not all compaction attempts succeed. When policy violations occur—such as missing checkpoints or concurrent modification conflicts—the system records a **compaction policy denial** in `memory_compaction_policy_denials`. The UI surfaces these failures through the error key `context_compaction_failed_open`, defined in [`packages/ui/src/materialize.ts`](https://github.com/apache/maka/blob/main/packages/ui/src/materialize.ts):

```typescript
// From materialize.ts - fallback copy when compaction context cannot be opened
export const COPY_CONTEXT_COMPACTION_FAILED_OPEN = 'context_compaction_failed_open';

```

This string renders a user-facing message explaining that the conversation context could not be reconstructed due to compaction.

### UI History Management

The composer layer maintains a **bounded in-memory history** separate from LTM compaction. In [`packages/ui/src/composer-helpers.ts`](https://github.com/apache/maka/blob/main/packages/ui/src/composer-helpers.ts):

```typescript
// Maximum entries kept for arrow-key navigation
export const COMPOSER_HISTORY_MAX_ENTRIES = 50;

// Append with automatic truncation
export function rememberComposerHistoryEntry(
  entries: ComposerHistoryEntry[],
  entry: ComposerHistoryEntry
): ComposerHistoryEntry[] {
  const updated = [...entries, entry];
  // Oldest entries drop off when exceeding 50
  return updated.slice(-COMPOSER_HISTORY_MAX_ENTRIES);
}

```

The `reconcileHistorySync` function merges this bounded history with `localStorage`, handling three states:
- **Empty persisted state**: Resets navigation index to -1
- **Null persisted state** (read failure): Preserves in-memory entries
- **Valid persisted state**: Replaces current history with stored version

## Context Budget Policy Implementation

While compaction manages storage bounds, **context budgets** enforce runtime token limits that prevent prompt overflow.

### Budget Definition and Display

Each session (and constituent skills) may declare a token budget. The UI renders this as a usage chip showing "spent / budget" format. In [`packages/ui/src/session-context-layer.tsx`](https://github.com/apache/maka/blob/main/packages/ui/src/session-context-layer.tsx), the display logic follows this pattern:

```typescript
/** When present (a budget exists), the chip shows spent / budget. */
interface SessionContextLayerProps {
  budget?: {
    spent: number;
    limit: number;
  };
}

```

The chip appears conditionally—only when a budget is configured for the current session context.

### Budget Enforcement Flow

1. **Token accounting**: The runtime deducts generated tokens from `budget.spent` after each model turn
2. **Threshold checking**: Before initiating a new generation, the system verifies sufficient headroom exists
3. **UI gating**: When `spent >= limit`, interactive elements (continue buttons, send actions) disable until budget refresh

### Interaction with Compaction

Budget exhaustion can trigger **preventive compaction**. The telemetry system tracks these decisions:

```typescript
// From telemetry-file-schema.ts - compaction decision tracking
interface CompactionDecisions {
  budgetForced: number;      // Compactions triggered by budget limits
  storageForced: number;     // Compactions triggered by storage pressure
  policyDenied: number;      // Failed compaction attempts
}

```

Operators monitor `budgetForced` versus `storageForced` ratios to tune budget allocations.

## Practical Integration Example

```typescript
import { 
  rememberComposerHistoryEntry,
  navigateComposerHistory,
  reconcileHistorySync 
} from '@maka/ui/composer-helpers';

// 1. Initialize with persisted history or empty array
let history = reconcileHistorySync([], localStorage.getItem('composerHistory'));

// 2. User submits prompt - append with automatic 50-entry limit
history = rememberComposerHistoryEntry(history, {
  role: 'user',
  content: userInput,
  timestamp: Date.now()
});

// 3. Arrow-up navigation retrieves previous entry
const { value } = navigateComposerHistory(
  { entries: history, index: -1, savedDraft: '' },
  'previous',
  currentDraft
);

// 4. Storage layer handles compaction independently
//    Budget exhaustion may trigger automatic checkpointing

```

## Key Source Files Reference

| Component | Path | Responsibility |
|-----------|------|---------------|
| Composer history helpers | [`packages/ui/src/composer-helpers.ts`](https://github.com/apache/maka/blob/main/packages/ui/src/composer-helpers.ts) | 50-entry bounded history, navigation, localStorage reconciliation |
| Budget UI layer | [`packages/ui/src/session-context-layer.tsx`](https://github.com/apache/maka/blob/main/packages/ui/src/session-context-layer.tsx) | Token usage chip, budget presence detection |
| Compaction storage | [`packages/storage/src/sqlite-long-term-memory-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/sqlite-long-term-memory-store.ts) | Checkpoint persistence, LTM operations |
| Compaction schema | [`packages/storage/src/sqlite-long-term-memory-schema.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/sqlite-long-term-memory-schema.ts) | `memory_compaction_policy_denials` table structure |
| Telemetry | [`packages/storage/src/telemetry-file-schema.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/telemetry-file-schema.ts) | `compactionDecisions` counter definitions |
| Error handling | [`packages/ui/src/materialize.ts`](https://github.com/apache/maka/blob/main/packages/ui/src/materialize.ts) | `context_compaction_failed_open` copy constants |

## Summary

- **History compaction** archives older transcripts via checkpoint IDs stored in SQLite, with `COMPOSER_HISTORY_MAX_ENTRIES = 50` bounding the active navigation history
- **Context budgets** enforce per-session token limits rendered as "spent / budget" chips in [`session-context-layer.tsx`](https://github.com/apache/maka/blob/main/session-context-layer.tsx)
- **Failure modes** are logged to `memory_compaction_policy_denials` and surfaced through [`materialize.ts`](https://github.com/apache/maka/blob/main/materialize.ts) error keys
- **Telemetry integration** enables monitoring of budget-forced versus storage-forced compaction decisions

## Frequently Asked Questions

### How does Maka decide when to compact history?

Maka compacts history when storage receives an explicit compaction trigger or when context budget limits would be exceeded. The [`sqlite-long-term-memory-store.ts`](https://github.com/apache/maka/blob/main/sqlite-long-term-memory-store.ts) module writes a `compactionCheckpointId` marking the archive boundary, while telemetry tracks whether compactions are budget-forced or storage-forced.

### What happens if I navigate backward through history after compaction?

The in-memory history retained for navigation—capped at 50 entries in [`composer-helpers.ts`](https://github.com/apache/maka/blob/main/composer-helpers.ts)—remains available for arrow-key traversal. Older entries beyond the checkpoint require reconstruction from LTM storage; if that fails, the UI displays `context_compaction_failed_open` from [`materialize.ts`](https://github.com/apache/maka/blob/main/materialize.ts).

### Can context budgets be configured per skill rather than per session?

Yes. The [`session-context-layer.tsx`](https://github.com/apache/maka/blob/main/session-context-layer.tsx) component receives budget data through props, and the underlying system supports skill-level budget declarations. Each skill's token consumption aggregates to the session total shown in the budget chip.

### Where are compaction policy violations recorded?

Failed compaction attempts are written to the `memory_compaction_policy_denials` table defined in [`sqlite-long-term-memory-schema.ts`](https://github.com/apache/maka/blob/main/sqlite-long-term-memory-schema.ts). This schema enables debugging of checkpoint conflicts and policy enforcement gaps without interrupting user sessions.