## ADDED Requirements

### Requirement: Shared type system

The system SHALL define a shared set of types used by all packages:
- `EvaluatorResult` — TypedDict with `key: string`, `score: number | boolean`, `comment?: string`, `metadata?: Record<string, unknown>`, `source_run_id?: string`
- `ModelClient` — Protocol with `chat.completions.create()` for LLM access
- `SandboxProvider` — Interface for provider-agnostic sandbox creation/management
- `Checkpointer` — Interface for checkpoint persistence
- `Serializable` — Interface requiring `toJSON()` and static `fromJSON()` methods
- All evaluators SHALL accept a consistent call signature: `(inputs?, outputs, reference_outputs?, **kwargs)`
- Error types: `GraphInterrupt`, `SandboxError`, `EvalError`

#### Scenario: EvaluatorResult conforms to schema

- **WHEN** an evaluator returns a result
- **THEN** the result SHALL conform to `EvaluatorResult` with at least `key` and `score`

#### Scenario: All stateful objects are serializable

- **WHEN** a `Sandbox`, `Snapshot`, or `Command` instance is serialized via `toJSON()`
- **THEN** a subsequent `fromJSON()` call SHALL reconstruct an equivalent instance

### Requirement: Serialization protocol

All stateful objects (`Sandbox`, `Session`, `Command`, `Snapshot`, `GraphState`) SHALL implement `toJSON()` / `fromJSON()` static methods for cross-session persistence.

#### Scenario: Round-trip serialization preserves identity

- **WHEN** an object is serialized and deserialized
- **THEN** the deserialized object SHALL have matching identity fields (`id`, `name`, `sessionId`)
