# Reasonix Extension Runtime Set Management and Snapshot Mechanisms Explained

> Understand Reasonix extension runtime set management and snapshot mechanisms. Learn how Reasonix guards UI extensions and validates backend state for seamless user prompt integration.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: internals
- Published: 2026-08-07

---

**Reasonix treats every UI side-car extension as a runtime set guarded by generation fences, while using timestamp-based snapshot validation to ensure backend runtime state never overwrites fresh user prompts.**

Reasonix, the AI coding assistant interface in the `esengine/DeepSeek-Reasonix` repository, handles UI extensions (plugins) through a sophisticated state management layer. Understanding the **runtime set management and snapshot mechanisms for extensions in Reasonix** is essential for developers building side-car plugins or debugging state synchronization issues between the TypeScript frontend and Go backend.

## Runtime Set Management Architecture

Reasonix models every extension surface as a *runtime set* living inside the per-tab controller state. The system uses deterministic identity keys and optimistic generation counters to maintain consistency across wire events.

### Surface Keys and Identity

Every extension surface is identified by a deterministic **surface key** constructed as `<pluginId>:<surfaceId>`. The `extensionSurfaceKey` utility in [`desktop/frontend/src/lib/useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/useController.ts) generates these identifiers:

```typescript
export function extensionSurfaceKey(surface: Pick<WireExtensionSurface, "pluginId" | "surfaceId">): string {
  return `${surface.pluginId}:${surface.surfaceId}`;
}

```

This string key serves as the primary index for all extension-related collections in the controller state.

### The Three Extension Collections

The controller maintains three distinct collections to track extension state, as implemented in [`useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/useController.ts):

- **`extensionStatuses`** – Stores the latest status metadata (`label`, `detail`, `severity`, `progress`) for every active surface.
- **`extensionForm`** – Holds the currently active form surface, enforcing a singleton constraint where only one form can be pending per tab.
- **`extensionNotifications`** – Queues transient toast-style notifications until the UI drains them.

These collections are updated atomically through the reducer to prevent partial state corruption.

### Generation Fencing

All three collections are protected by a **generation fence** that prevents out-of-order updates from stale runtime epochs. Every surface event carries an optional `generation` number, and the controller only accepts events with a generation newer than or equal to the last stored value.

The acceptance logic lives in `acceptsExtensionGeneration` at lines 24-26 of [`useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/useController.ts):

```typescript
export function acceptsExtensionGeneration(stored: number | undefined, incoming: number | undefined): boolean {
  return incoming === undefined || stored === undefined || incoming >= stored;
}

```

This function returns `true` for undefined values (backward compatibility) or when the incoming generation advances the state.

### Event Processing Pipeline

When wire events arrive via the `extension_surface` channel, the controller routes them through `applyExtensionSurfaceEvent` (lines 70-92 of [`useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/useController.ts)). The pipeline uses `withAcceptedExtensionGeneration` to gate updates:

1. **Status events** trigger `applyExtensionStatus`, writing into `extensionStatuses`.
2. **Card events** trigger `applyExtensionCard`, adding or replacing an `ExtensionItem` in `state.items`.
3. **Form events** trigger `applyExtensionForm`, storing the form in `state.extensionForm`.
4. **Notification events** trigger `applyExtensionNotification`, pushing onto `state.extensionNotifications`.

Only events passing the generation fence modify state; stale events are silently discarded.

## Runtime Snapshot Mechanisms

Reasonix takes **runtime snapshots** from the Go backend via the `runtime` channel to synchronize execution state. These snapshots require careful validation to prevent them from overwriting newer UI state.

### RuntimeMetaSnapshot Structure

Snapshots are represented by the `RuntimeMetaSnapshot` type defined in [`useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/useController.ts):

```typescript
type RuntimeMetaSnapshot = {
  running: boolean;
  pendingPrompt?: boolean;
  backgroundJobs?: number;
  cancelRequested?: boolean;
  cancellable?: boolean;
};

```

This structure captures whether the backend is executing code, waiting for user approval, or processing background jobs.

### Staleness Detection Logic

To determine if a snapshot predates user interaction, Reasonix compares the snapshot timestamp (`snapshotAt`) against the prompt arrival time (`promptArrivedAt`). The `runtimeSnapshotPredatesPrompt` function encapsulates this check:

```typescript
export function runtimeSnapshotPredatesPrompt(
  state: { approval?: unknown; ask?: unknown; promptArrivedAt?: number } | undefined,
  snapshotAt: number | undefined,
): boolean {
  if (!state || (!state.approval && !state.ask)) return false;
  if (snapshotAt === undefined || state.promptArrivedAt === undefined) return false;
  return snapshotAt <= state.promptArrivedAt;
}

```

When this returns `true`, the controller discards the snapshot and schedules a refetch after a debounce interval defined by constants like `STALE_TURN_RECONCILE_MS` and `STALE_PROMPT_RECONCILE_MS` (lines 42-50 of [`useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/useController.ts)).

### Snapshot-to-Prompt Validation

The validation mechanism protects against race conditions where a stale snapshot arrives after a user has already submitted a new prompt. The controller checks `runtimeSnapshotPredatesRetry` for similar logic against retry timestamps. If either check fails, the UI retains its current state rather than reverting to the snapshot's view.

### Foreground State Translation

The `foregroundRunningFromRuntimeMeta` function (lines 90-93 of [`useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/useController.ts)) translates backend snapshots into UI-ready state:

```typescript
export function foregroundRunningFromRuntimeMeta(meta: RuntimeMetaSnapshot): boolean {
  if (typeof meta.cancellable === "boolean") return meta.cancellable;
  if ((meta.backgroundJobs ?? 0) > 0 && !meta.pendingPrompt) return false;
  return Boolean(meta.running);
}

```

This handles edge cases such as background jobs without pending prompts, ensuring the loading indicator reflects actual foreground execution status.

## Practical Implementation Examples

### Publishing Extension Status from a Side-Car

Extension plugins publish updates via the wire protocol, bumping the generation to ensure ordering:

```typescript
await fetch("/api/extension_surface", {
  method: "POST",
  body: JSON.stringify({
    kind: "status",
    pluginId: "my-plugin",
    surfaceId: "status-panel",
    generation: 2,
    status: { label: "Ready", severity: "info" }
  })
});

```

The frontend receives this event, computes the surface key as `"my-plugin:status-panel"`, validates the generation via `acceptsExtensionGeneration`, and updates `state.extensionStatuses` accordingly.

### Detecting Stale Snapshots

Components can guard against snapshot corruption using the predication helper:

```typescript
if (runtimeSnapshotPredatesPrompt(currentState, snapshotAt)) {
  scheduleRefetch();
  return; // Ignore stale snapshot
}

```

This pattern prevents the UI from clearing a pending approval dialog when an older runtime snapshot arrives over the wire.

## Summary

- **Surface keys** use the format `<pluginId>:<surfaceId>` to uniquely identify extension runtime sets in the controller state.
- **Generation fences** in `acceptsExtensionGeneration` ensure only newer or equal generation events update `extensionStatuses`, `extensionForm`, or `extensionNotifications`.
- **Runtime snapshots** arrive as `RuntimeMetaSnapshot` objects from the Go backend and must pass staleness checks against `promptArrivedAt` timestamps.
- **Staleness detection** via `runtimeSnapshotPredatesPrompt` prevents outdated backend state from overwriting fresh user interactions.
- All logic is centralized in [`desktop/frontend/src/lib/useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/useController.ts), with supporting types in [`desktop/frontend/src/lib/types.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/types.ts).

## Frequently Asked Questions

### How does Reasonix prevent race conditions between extension updates and runtime snapshots?

Reasonix uses orthogonal validation strategies: extension updates are gated by integer **generations** (monotonic counters per surface), while runtime snapshots are validated against **timestamps** comparing `snapshotAt` with `promptArrivedAt`. The `withAcceptedExtensionGeneration` guard (lines 99-103 of [`useController.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/useController.ts)) applies to both event types, ensuring only fresh state survives regardless of network ordering.

### What happens when an extension sends an event with an older generation number?

The `acceptsExtensionGeneration` function returns `false` when the incoming generation is less than the stored value, causing the reducer to discard the event silently. This prevents out-of-order wire events from reverting the UI to previous states, which is critical when users rapidly interact with extension forms or status panels.

### Can multiple extension forms be active simultaneously in Reasonix?

No. The controller enforces a singleton constraint on forms through the `extensionForm` collection. When `applyExtensionForm` processes a new form event, it replaces any existing form in the state. This design prevents modal conflicts where multiple plugins might request user input simultaneously.

### Where does the backend runtime snapshot originate, and how often is it sent?

Snapshots originate from the Go backend via the `runtime` channel (connected in [`desktop/frontend/src/lib/bridge.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/bridge.ts)) and represent the current execution meta-state. The backend emits these during state transitions (start/stop of execution, prompt requests), and the frontend debounces rapid updates using constants like `STALE_TURN_RECONCILE_MS` to avoid UI flicker.