Bounded Observation Limits and State Eviction Policies in pi-computer-use

The pi-computer-use framework stores UI observations in an immutable, insertion-ordered StateStore bounded to 128 entries, evicting the oldest observations via FIFO policy when capacity is exceeded and throwing deterministic errors for evicted state references.

The pi-computer-use repository implements a deterministic observation management system that balances memory efficiency with reliable UI automation. Understanding the bounded observation limits and state eviction policies is essential for building resilient client code that handles resource epochs gracefully. The architecture guarantees that old observations either resolve exactly or fail clearly, preventing silent data corruption.

The 128-Entry Bounded Store Architecture

In src/state.ts, the framework defines SavedStates using a bounded capacity store:

new StateStore<UiObservation>(128)   // bounded to 128 entries

This immutable, insertion-ordered store maintains UI observations in a strict FIFO queue. Each observation persists for the duration of its resource epoch, ensuring that references remain valid only while the observation occupies a slot within the bounded buffer.

The generic StateStore implementation in src/runtime.ts provides the underlying mechanics for this bounded storage, enforcing capacity limits without compromising performance.

FIFO Eviction Mechanics

When the store reaches its 128-entry capacity, the oldest entries are evicted using FIFO (First-In-First-Out) ordering. This eviction policy ensures predictable memory usage while maintaining a recent window of observable UI states.

Evicted observations trigger deterministic failures. The system in src/bridge.ts throws explicit errors such as "No observation state is available" or "Observation has been evicted" when client code attempts to reference a stateId that has been removed from the buffer. This design prevents silent fallbacks to stale data that could corrupt automation sequences.

State Scoping and Resource Epochs

Observations are state-scoped, meaning they can only be accessed via the specific stateId returned with the observation. This scoping mechanism creates distinct resource epochs where:

  • Valid stateId references resolve to their exact observation data
  • Invalid or evicted stateId values immediately produce errors
  • Client code must re-observe to obtain fresh state after eviction

According to the architecture documentation in docs/architecture.md, this bounded store model ensures that "old refs either resolve to their exact observation or fail clearly after eviction."

Handling Eviction in Client Code

Client implementations should treat stateId values as valid only while they remain in the bounded store. When act_ui() receives an evicted state reference, it throws an error requiring the client to re-observe.

Obtaining and using observations:

// Obtain a fresh observation
const {stateId, ...} = await observe_ui({ ... });

// Use refs from that observation in a later call
await act_ui({
  steps: [{ click: "@e12" }],   // "@e12" comes from the previous observation
  stateId,                     // Must match the observation that produced the ref
});

Graceful eviction handling:

// Handling eviction gracefully
try {
  await act_ui({ steps, stateId });
} catch (e) {
  if (e.message.includes("evicted")) {
    const fresh = await observe_ui({ ... });
    // retry with the new stateId
    await act_ui({ steps, stateId: fresh.stateId });
  } else {
    throw e;
  }
}

If the store has evicted the observation, act_ui throws: "Observation has been evicted – re‑observe before proceeding."

Key Implementation Files

The bounded observation system spans several critical source files:

  • src/state.ts: Defines SavedStates with StateStore<UiObservation>(128) and eviction logic
  • src/runtime.ts: Implements the generic StateStore used for bounded observation storage
  • src/bridge.ts: Throws errors when observations are missing or evicted
  • docs/architecture.md: Documents the immutable bounded-store model and FIFO eviction behavior

Summary

  • The observation store is bounded to 128 entries via StateStore<UiObservation>(128) in src/state.ts
  • FIFO eviction removes the oldest observations when capacity is exceeded, ensuring predictable memory usage
  • Access requires valid state-scoped stateId values that fail deterministically after eviction
  • Client code must re-observe to obtain fresh state IDs when encountering eviction errors
  • The architecture prevents silent stale data usage by throwing explicit errors in src/bridge.ts

Frequently Asked Questions

What happens when the observation store reaches 128 entries?

When the StateStore capacity is exceeded, the oldest entries are evicted using FIFO ordering. New observations continue to be inserted while the oldest resource epochs are removed, ensuring the store never grows beyond its fixed 128-entry limit.

How do I handle "observation has been evicted" errors?

Wrap act_ui calls in try-catch blocks to detect eviction messages. When caught, call observe_ui() to generate a fresh observation with a new stateId, then retry the action using the updated state reference.

Why are observations scoped to specific state IDs?

State scoping ensures that UI element references (like "@e12") are only valid within the specific observation that created them. This prevents automation scripts from accidentally interacting with outdated UI elements after the interface has changed, as invalid references throw clear errors rather than performing dangerous stale operations.

Where is the bounded store limit configured?

The 128-entry limit is hardcoded in src/state.ts where SavedStates is instantiated as new StateStore<UiObservation>(128). This fixed capacity balances memory constraints against the need for recent observation history in UI automation workflows.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →