> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sovseal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deterministic Lineage: Sequence Numbers, Point-in-Time Recovery, and Verified Restore

> How sovseal orders state snapshots by a strict per-agent sequence number, enables point-in-time recovery via restoreAt, and verifies every restore — no content-hash chain, no fork/rollback primitives.

<style>
  {`
      main, article, .prose {
        margin-left: 2.5cm !important;
        margin-right: 2.5cm !important;
      }
      `}
</style>

sovseal orders an agent's state checkpoints as a strict, per-agent sequence — not a mutable "latest state" row. Every snapshot the server has ever confirmed for an agent stays retrievable by its sequence number, which is what makes point-in-time recovery and crash-safe replication structural properties of the system rather than special-case code.

<Note>
  This page covers the **`snapshot`/`restore`/`lineage` state-replication system**. It does not apply to `store`/`recall` semantic memory, which has no sequencing or lineage concept — see [Memory Model](/platform/core-concepts/memory-model) for how the two systems differ.
</Note>

***

## Sequence numbers, not content hashes, define order

Each `agent_id` has its own independent sequence starting at `0`. The server enforces order at write time: a `snapshot()` call's `sequence_number` must equal `latest confirmed sequence for this agent + 1`, or it's rejected with `409 sequence_gap`. The very first snapshot for a new agent must be `sequence_number: 0` with `parent_snapshot: null` — this genesis check is what proves a chain has no missing prefix.

```text theme={null}
agent "trading-bot-7"
  seq 0 (genesis) ── seq 1 ── seq 2 ── seq 3
                                        ▲
                                latest confirmed
```

Retrying the same `(agent_id, sequence_number)` with an unchanged `client_payload_hash` is idempotent — the server returns the original receipt rather than erroring, which is what makes replay-after-crash safe. The same sequence number with a *different* hash is a real conflict (`409 sequence_conflict`): two different payloads are trying to claim the same position, and the server refuses to silently pick a winner.

## Point-in-time recovery: `restoreAt`, not rollback

There is no `rollback()` call that moves a "current state" pointer. Instead:

* `restore({ agentId })` fetches the **latest confirmed** checkpoint.
* `restoreAt({ agentId, sequence })` fetches the checkpoint at **any specific sequence number** in that agent's history — including ones that are no longer the latest.

Because every sequence number is permanently retrievable, "going back to how things looked three checkpoints ago" is just calling `restoreAt` with that number — nothing is deleted, nothing needs to be un-done. Nothing about calling `restoreAt` on an old sequence affects what `restore()` returns afterward; the server's "latest" pointer only ever moves forward via new `snapshot()` calls.

## "Branching" means a new agent\_id

sovseal has no `fork()` primitive. If you want two independent lines of state descending from the same point, the pattern is: `restoreAt` the checkpoint you want to branch from, decrypt and verify it (see [Verified Semantic Recall](/platform/core-concepts/verified-semantic-recall)), then call `snapshot()` for that payload as **sequence `0` under a new `agent_id`**. The two agent IDs then have fully independent sequence chains — there's no shared ancestry tracked by the server beyond whatever you encode into the payload yourself.

## Every restore is verified, not just fetched

`restore`/`restoreAt` return `{ receipt, ciphertextUrl }` — metadata and an encrypted blob, not verified plaintext. The receipt's `client_payload_hash` is an anchor you check yourself: decrypt, re-derive `sha256(canonicalize(payload))`, and compare. A mismatch means either the ciphertext was tampered with (the AES-GCM auth tag catches this) or a different valid record was substituted in its place (the hash comparison catches this, because the hash covers the whole payload including its `sequence_number` and `parent_snapshot`). See [Verified Semantic Recall](/platform/core-concepts/verified-semantic-recall) for the full two-check pattern and a ready-to-use implementation — this is not automatic, you must run it.

## Crash safety and conflicting writers

Local durability and replication crash-safety are properties of the write-behind sync worker, not of the SDK's snapshot/restore calls themselves — see [Replication & Sync](/platform/features/replication-sync) for the full mechanics: the local LanceDB write-ahead log, the sync worker's poll/retry loop, and what happens when two writers collide on the same sequence number (a **split-brain halt**, not an automatic merge — sovseal refuses to guess which version is correct).

***

## Next steps

<CardGroup cols={2}>
  <Card title="Memory Model" icon="layer-group" href="/platform/core-concepts/memory-model">
    The full record shape for both semantic memory and state snapshots, and the complete SDK method table.
  </Card>

  <Card title="Verified Semantic Recall" icon="shield" href="/platform/core-concepts/verified-semantic-recall">
    The tamper/substitution check you run on every restore — with working code.
  </Card>

  <Card title="Replication & Sync" icon="arrows-rotate" href="/platform/features/replication-sync">
    The write-behind worker: batching, retry, idempotent replay, and split-brain handling.
  </Card>

  <Card title="Zero-Knowledge Guarantees" icon="lock" href="/platform/core-concepts/zero-knowledge">
    How lineage integrity fits into the broader cryptographic threat model.
  </Card>
</CardGroup>
