Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.protean.peerislands.io/llms.txt

Use this file to discover all available pages before exploring further.

The replay gate runs a fixed agent (hello) with a fixed seed, captures the event log, and asserts it matches a committed cassette byte-for-byte. It runs in CI on every PR.

Why a gate, not a test

Tests fail loudly when assertions break. Determinism breaks quietly — a Date.now() slipped in, a random ID generator, a non-stable Map ordering. The gate’s job is to catch the break at the source, not three slices later when an LLM response shifts because of a millisecond timestamp in the prompt.

What the gate does

bun run --filter @protean/e2e test:replay
  1. Runs the hello agent live with seed = "hello-replay-gate-v1".
  2. Normalizes the event log (strips wall-clock ts fields).
  3. Loads e2e/cassettes/hello-replay-gate-v1.events.json (committed).
  4. Asserts the two are identical (runId, stepId, kind, payload).
The cassette filename is versioned by seed. Bumping the seed creates a new cassette next to the old; the old keeps working until removed.

When the gate fails

A failure means non-determinism crept in. Don’t suppress it. Trace the diff (the gate prints the first divergent event), find the source (almost always: a wall-clock read, a random call, an unsorted iteration), route it through @protean/runtime’s clock/random. Re-recording the cassette is allowed only when the divergence is intentional — an event-shape change, a new event kind, a deliberately-different agent. In that case, bump the seed version and ship both old + new for a transition.