# How DisplayState Flows Through Magnitude: Materialization, Streams, and Client Synchronization

> Understand DisplayState flow in Magnitude. Learn about UI intent, materialization, streams, and client sync with speculative mutations for efficient state management.

- Repository: [Magnitude/magnitude](https://github.com/magnitudedev/magnitude)
- Tags: internals
- Published: 2026-09-06

---

**DisplayState in Magnitude flows from UI intent through a shape-keyed subscription system, where the ACN materializes windowed views as complete snapshots followed by incremental patches, and the client reconciles these with speculative mutations in a reference-preserving store.**

Magnitude's display system treats every UI view as a **shape-keyed, windowed observation** of session state. This article traces the complete pipeline—from shape derivation through agent materialization to client-side rendering—using the actual source code from the `magnitudedev/magnitude` repository.

---

## From UI Intent to DisplayViewShape

Every display update begins with user interaction. The **display controller** ([`packages/client-common/src/display-view-controller/controller.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/display-view-controller/controller.ts)) translates UI actions into a structured `DisplayViewShape` that declares exactly which timelines and windows the client needs.

```ts
// controller.ts – building the desired shape
const desiredShape = displayShapeFor(
  snapshot.rootTailLimit,
  snapshot.expandedForkStack,
  snapshot.displayMode,
);

```

The `displayShapeFor` function in [`packages/client-common/src/sync/display-view-shape.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/sync/display-view-shape.ts) encodes this as a root tail window plus per-fork windows for worker timelines:

```ts
export const displayShapeFor = (rootLimit, requestedWorkerForkIds, presentation = 'default') => ({
  timelines: {
    root: timelineTail(rootLimit, presentation),
    ...Object.fromEntries(
      requestedWorkerForkIds.map(id => [forkIdToKey(id), timelineTail(WORKER_TIMELINE_LIMIT, presentation)])
    ),
  },
});

```

This shape becomes the identity for all downstream caching and deduplication.

---

## Opening the StreamDisplayView Subscription

The controller opens a **Query subscription** defined in [`packages/client-common/src/operations/display.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/operations/display.ts):

```ts
export const Display = Group.make({
  StreamDisplayView: subscription(
    Rpcs.streamDisplayView,
    client => client.display.streamDisplayView,
    { gcTime: "5 seconds" }, // GC after last observer leaves
  ),
});

```

The controller invokes it with the current `sessionId` and computed `shape`:

```ts
const subscription = this.client.Display.StreamDisplayView({ sessionId, shape });

```

This subscription is the single entry point for all display state flowing from agent to client.

---

## ACN Boundary: Shared DisplayViewStreams and Shape Deduplication

On the ACN (Agent Connection Node), all subscriptions for identical shapes are **deduplicated** by `DisplayViewStreams` in [`packages/acn/src/display-view-streams.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn/src/display-view-streams.ts). The deduplication key is a SHA-256 hash of the canonical shape:

```ts
export const displayViewId = (shape) =>
  `shape:${createHash('sha256')
    .update(Key.canonical(shape))
    .digest('hex')
    .slice(0, 16)}`;

```

`DisplayViewStreams` manages two critical aspects:

- **Registration**: A PubSub of events with reference-counted subscribers
- **Materialization**: When the first subscriber appears, it acquires the session runtime, calls `setShape`, then `snapshot` to produce the initial state

The `attachUnlocked` and `materialize` methods handle this lazy initialization.

---

## Materializing the View: Snapshot and Patch Events

The actual materialization logic lives in [`packages/acn/src/display-view-stream.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn/src/display-view-stream.ts). This module creates a stream that emits:

1. **Full state** (`DisplayViewStateEvent`) on subscription open or explicit snapshot request
2. **Decoded JSON patches** (`DisplayViewPatchEvent`) for incremental changes, computed with `diffDecoded` from `@magnitudedev/utils/patch`

```ts
const displayEvents = Stream.merge(liveStates, snapshotStates).pipe(
  Stream.mapAccumEffect(Option.none<DisplayViewSnapshot>(), (prev, next) =>
    // on first event or on explicit resync: send full state
    // otherwise compute diff → patch event
  ),
);

```

The mixed stream of state, patch, and restore-queued-messages events flows to the client through `rawStream`. The subscription is reference-counted; when the last client observer leaves, `close` is triggered on the agent side, releasing the runtime view.

---

## Client-Side Store: Receiving and Merging State

The client receives events via the `DisplayReader`/`DisplaySpeculator` API, implemented by **SpeculativeDisplayViewStore** in [`packages/client-common/src/sync/display-view-store.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/sync/display-view-store.ts). This store maintains three critical pieces of state:

- **`this.accepted`**: The authoritative snapshot from the agent
- **`this.transactions`**: Pending speculative mutations from local UI actions
- **`this.rendered`**: The computed view = accepted + speculative transactions

Incoming events are processed through the `accept` method:

```ts
accept = (next) => {
  if (this.transactions.length === 0) {
    this.accepted = next;
    this.rendered = next;
    this.notify();
    return;
  }
  // Conflict detection & recompute when speculative txs exist…
}

```

- **State events**: Replace `accepted` and reset speculative transactions if they conflict (using write-key conflict detection)
- **Patch events**: Applied with `applyDecodedPatch` via `deriveMutation`

The store notifies React through `useSyncExternalStore` in the `useDisplayView` hook ([`packages/client-common/src/sync/use-display-view.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/sync/use-display-view.ts)).

---

## Practical Examples: Working with DisplayState

These examples show how to interact with the display system at different layers.

### Reading Display State in a React Component

Pull a memoized slice of the root timeline; updates are reference-equal when unchanged, preventing unnecessary re-renders:

```tsx
import { useDisplayView } from '@/client-common/src/sync/use-display-view';
import { selectRootMessages } from '@magnitudedev/sdk';

export function ChatLog() {
  const messages = useDisplayView(selectRootMessages);
  return (
    <ul>
      {messages.map(m => (
        <li key={m.id}>{m.content}</li>
      ))}
    </ul>
  );
}

```

### Expanding the Window on Scroll

Increase the root tail limit when the user approaches the top of the view:

```ts
import { controller } from '@/client-common/src/display-view-controller/controller';

function onScroll(visibleCount: number) {
  const needed = visibleCount + 200;
  controller.declareRootTailLimit(needed);
}

```

`declareRootTailLimit` recomputes the shape, triggers `openView()`, and the ACN materializes a larger snapshot automatically.

### Applying Speculative Mutations

Optimistically add a user message before server acknowledgment:

```ts
import { displaySync } from '@/client-common/src/sync/display-view-store';

const handle = displaySync.mutate(
  { owner: 'ui', label: 'Add message' },
  (draft) => {
    draft.state.messages.byId['msg-123'] = {
      id: 'msg-123',
      content: 'Hello, world!',
      type: 'user_message',
      timestamp: Date.now(),
    };
    draft.state.messages.order.push('msg-123');
  },
);

```

If a later server snapshot already contains this message, `SpeculativeDisplayViewStore` detects the conflict via write-key comparison and removes the obsolete speculative transaction automatically.

---

## Key Source Files and Responsibilities

| Responsibility | Path |
|---|---|
| Architecture overview | [`info/display-architecture.md`](https://github.com/magnitudedev/magnitude/blob/main/info/display-architecture.md) |
| Agent-side view semantics | [`info/agent/display-views.md`](https://github.com/magnitudedev/magnitude/blob/main/info/agent/display-views.md) |
| Shape generation | [`packages/client-common/src/sync/display-view-shape.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/sync/display-view-shape.ts) |
| Display controller | [`packages/client-common/src/display-view-controller/controller.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/display-view-controller/controller.ts) |
| RPC subscription definition | [`packages/client-common/src/operations/display.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/operations/display.ts) |
| ACN shared stream manager | [`packages/acn/src/display-view-streams.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn/src/display-view-streams.ts) |
| ACN per-view stream logic | [`packages/acn/src/display-view-stream.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn/src/display-view-stream.ts) |
| Client store & speculation | [`packages/client-common/src/sync/display-view-store.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/sync/display-view-store.ts) |
| React hook | [`packages/client-common/src/sync/use-display-view.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/sync/use-display-view.ts) |

---

## Summary

- **Shape derivation**: UI actions become `DisplayViewShape` via `displayShapeFor`, defining exactly what timelines and windows to observe
- **Subscription**: `StreamDisplayView` opens a shape-keyed, deduplicated stream to the ACN
- **Materialization**: `DisplayViewStreams` lazily acquires the session runtime, emits a full `DisplayViewStateEvent`, then `DisplayViewPatchEvent` diffs for subsequent changes
- **Client reconciliation**: `SpeculativeDisplayViewStore` merges authoritative state with speculative mutations, using write-key conflict detection
- **React integration**: `useDisplayView` exposes the rendered state through `useSyncExternalStore` with reference-preserving updates

The entire pipeline is optimized for minimal data transfer (patches over full snapshots), automatic deduplication across clients viewing the same shape, and seamless optimistic UI through speculative transactions.

---

## Frequently Asked Questions

### How does Magnitude avoid sending full snapshots on every update?

The ACN materializes an initial complete snapshot (`DisplayViewStateEvent`), then computes incremental `DisplayViewPatchEvent` messages using `diffDecoded` from `@magnitudedev/utils/patch`. This JSON Patch-based approach transmits only changed fields. See [`packages/acn/src/display-view-stream.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn/src/display-view-stream.ts) for the `mapAccumEffect` logic that alternates between full state and diff computation.

### What happens when multiple clients request the same view shape?

`DisplayViewStreams` in [`packages/acn/src/display-view-streams.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn/src/display-view-streams.ts) deduplicates by SHA-256 hash of the canonical shape. A single materialized view serves all subscribers; reference counting manages lifecycle. When the last subscriber disconnects, the stream closes and the runtime view is released.

### How does speculative UI handle server reconciliation?

`SpeculativeDisplayViewStore` maintains `accepted` (authoritative) and `rendered` (accepted + pending transactions) states. Incoming snapshots are compared against speculative write-keys. If the server state already contains a transaction's changes, that transaction is dropped automatically without visual flicker. Conflicting transactions trigger recomputation from the new accepted state.

### Why does the controller use a 5-second GC time for subscriptions?

The `gcTime: "5 seconds"` option in [`packages/client-common/src/operations/display.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/operations/display.ts) allows brief disconnection—such as component unmount/remount during navigation—without tearing down the ACN-side stream. This prevents unnecessary re-materialization when the user quickly returns to a view, while still releasing resources after genuine abandonment.