# `CMDC.Checkpoint.Snapshot`
[🔗](https://github.com/tuplehq/cmdc/blob/v0.4.0/lib/cmdc/checkpoint/snapshot.ex#L1)

会话快照标准 payload。

统一 `CMDC.Checkpoint.save/3` 的输出与 `load/2` 的输入。
含 `@schema_version` 便于未来 schema 演进时向前兼容。

## 不可序列化字段策略

Agent.State 中以下字段在 `save/2` 时会被**自动剥离**，
并在 `resume_session!/2` 时由 plugin `:session_start` hook 重建：

- `pid()` 字段（如 `:agent_pid` / `:owner_pid`）
- `Stream` / `Task` 引用
- `:reference` 字段（如 `:monitor_ref`）

这一策略避免序列化死引用、同时保证 plugin 状态可以靠
`:session_start` 重新初始化。Snapshot 会保留这些字段名加 `:_stripped` 标记
以便恢复时知道哪些 plugin 需要重置。

## Examples

    iex> snap = Snapshot.new(session_id: "sess-1", state: %{messages: []})
    iex> snap.schema_version
    1

# `serializable`

```elixir
@type serializable() :: map() | struct()
```

可被序列化为 snapshot 的负载（通常是 `Agent.State` 或 map）。

# `t`

```elixir
@type t() :: %CMDC.Checkpoint.Snapshot{
  checkpoint_id: String.t(),
  label: String.t() | nil,
  metadata: map(),
  saved_at: DateTime.t(),
  schema_version: pos_integer(),
  session_id: String.t(),
  state: serializable(),
  stripped_fields: [atom()]
}
```

# `new`

```elixir
@spec new(keyword()) :: t()
```

构建新的 Snapshot，自动生成 `checkpoint_id` + `saved_at`，
并剥离不可序列化字段。

## 选项

- `:session_id` — 必填
- `:state` — 必填（Agent.State 或任意 map）
- `:label` — 可选标签
- `:metadata` — 用户附加 map（默认 `%{}`）

# `schema_version`

```elixir
@spec schema_version() :: pos_integer()
```

返回 schema 版本号常量。

---

*Consult [api-reference.md](api-reference.md) for complete listing*
