# Data Types

<!-- Canonical: https://www.atlaso.ai/docs/types/deposit -->

Every result type the SDK returns. All are frozen, slotted dataclasses with a stable wire format (`to_dict()` includes a `"kind"` discriminator). Internal `dataclasses.asdict()` is forbidden in public code by CI gate.

## `Deposit`

```python
@dataclass(frozen=True, slots=True)
class Deposit:
    id: str
    content: str
    polarity: Polarity                   # positive | negative | cautionary | open
    evidence_grade: EvidenceGrade        # anecdotal | observed | replicated | verified
    scope: Scope
    user_id: str
    tags: tuple[str, ...]
    contradicts: tuple[str, ...]
    artifact_refs: tuple[str, ...]
    created_at: datetime
    author: str | None
    author_role: str | None
    repro_status: ReproStatus            # unreplicated | replicated | failed_repro
    task_id: str | None
```

Immutable. To "edit" a deposit, call `contradict()`.

`deposit.to_dict()` produces a stable JSON shape:

```python
{
  "kind": "deposit",
  "id": "7e3a1b2c-…",
  "content": "Alice prefers oat milk",
  "polarity": "open",
  "evidence_grade": "anecdotal",
  "scope": {"model": None, "dataset": None, ...},
  "user_id": "alice",
  "tags": ["preference"],
  "contradicts": [],
  "artifact_refs": [],
  "created_at": "2026-05-11T14:23:00.123456+00:00",
  "author": None,
  "author_role": None,
  "repro_status": "unreplicated",
  "task_id": None,
}
```

---

## `SearchResult`

```python
@dataclass(frozen=True, slots=True)
class SearchResult:
    deposit: Deposit
    score: float
    is_confident: bool
    has_disagreement: bool
    agreement_score: float                 # [0, 1] — public alias for bag_precision
    is_thin_evidence: bool
    conflict_peers: tuple[str, ...] = ()

    # Hot-path property aliases (no __getattr__ magic):
    @property
    def id(self) -> str: ...
    @property
    def content(self) -> str: ...
    @property
    def polarity(self) -> Polarity: ...
    @property
    def evidence_grade(self) -> EvidenceGrade: ...
    @property
    def scope(self) -> Scope: ...
    @property
    def tags(self) -> tuple[str, ...]: ...

    def explain(self) -> str: ...
```

> **Not a `Deposit` subclass.** `isinstance(hit, Deposit)` is `False` on purpose. Composition, not inheritance — so legacy code that branches on the type can't silently drop the dispersion fields. Use `hit.deposit` when you need the underlying record.

### `SearchResults` (the container)

```python
@dataclass(frozen=True, slots=True)
class SearchResults:
    items: tuple[SearchResult, ...]
    has_disagreement: bool        # bag-level: any returned bag flagged
    is_confident: bool            # bag-level: at least one confident bag, no disagreement anywhere

    def __iter__(self): ...
    def __len__(self): ...
    def __getitem__(self, idx): ...
    def __bool__(self): ...
    def explain(self) -> str: ...
```

Iterable, length-able, indexable, truthy if non-empty. **Not a list subclass.**

`has_disagreement` is computed over every bag the engine returns, not just the sliced top-`limit`. A conflict can't hide from your agent because of pagination.

`result.to_dict()` uses `"kind": "search_result"` and flattens the most common Deposit fields to the top level so consumers can pull `r["content"]` without nesting through `r["deposit"]["content"]`.

---

## `Diagnostics` (Field Maturity Index)

```python
@dataclass(frozen=True, slots=True)
class Diagnostics:
    fmi: int              # 0..100
    coverage: float       # 0..1
    precision: float      # 0..1
    resolution: float     # 0..1
    density: float        # 0..1
    window_days: int
    deposit_count: int

    def explain(self) -> str: ...
```

### The formula

```python
FMI = 100 * (Coverage × Precision × Resolution × Density) ** (1/4)
```

Geometric mean, not arithmetic — a single weak pillar drops the score sharply. Intentional.

### The pillars

- **Coverage** — rolling 30-day fraction of `recall()` calls that returned at least one confident hit. Drops when users ask questions the field hasn't answered.
- **Precision** — average `bag_precision` across all multi-sample bags. Drops when bags are split.
- **Resolution** — fraction of conflict bags that have been *resolved* (at least one deposit is the target of a `contradicts` edge).
- **Density** — `1 − singleton_bags / total_bags`. Drops when most bags have only one deposit.

### Vacuous cases

Empty field → coverage 0.0, density 0.0. No multi-sample bags → precision 1.0 (vacuous). No conflicts → resolution 1.0 (vacuous).

```python
diag = user.health(window_days=30)
print(diag.fmi)         # e.g. 72
print(diag.explain())
# "Memory is healthy (FMI 72/100). Searches are returning confident answers."
```

---

## `AddResult`

```python
@dataclass(frozen=True, slots=True)
class AddResult:
    deposit: Deposit
    is_idempotent_replay: bool

    @property
    def id(self) -> str: ...
```

Returned by `add()` and `contradict()`. `is_idempotent_replay=True` when an identical-content write with the same key fell within the 24-hour window.

## `AddItem` (bulk import row)

```python
@dataclass(frozen=True, slots=True)
class AddItem:
    content: str
    idempotency_key: str          # REQUIRED — no default
    polarity: Polarity = "open"
    evidence_grade: EvidenceGrade = "anecdotal"
    scope: Scope | None = None
    tags: tuple[str, ...] = ()
    contradicts: tuple[str, ...] = ()
```

## `BulkReject`

```python
@dataclass(frozen=True, slots=True)
class BulkReject:
    item: AddItem
    error: Exception     # typically a subclass of AtlasoError
    index: int
```

## `AddManyResult`

```python
@dataclass(frozen=True, slots=True)
class AddManyResult:
    committed: tuple[Deposit, ...]
    duplicates: tuple[Deposit, ...]     # idempotent replays
    failed: tuple[BulkReject, ...]
    is_partial: bool = False

    @property
    def total(self) -> int: ...
    @property
    def all_succeeded(self) -> bool: ...
```

Skip-and-report. Successful items commit even if others fail.

## `RetractResult`

```python
@dataclass(frozen=True, slots=True)
class RetractResult:
    deposit_id: str
    mode: str                              # "soft" or "hard"
    contradicts_preserved: tuple[str, ...] = ()
```

`contradicts_preserved` is the tuple of deposit IDs whose `contradicts` edges pointed at the retracted deposit and remain intact (non-empty only after a soft retract).

## `PeekView`

```python
@dataclass(frozen=True, slots=True)
class PeekView:
    user_id: str
    deposits: tuple[Deposit, ...]
    total_count: int                 # excludes soft-retracted (tombstoned) rows
    fmi: int                         # 0..100
    has_recent_disagreements: bool

    def __iter__(self): ...
```

---

<!-- atlaso:doc-trailer -->
**Source:** <https://www.atlaso.ai/docs/types/deposit>  
**Edit on GitHub:** <https://github.com/imashishkh21/atlaso/tree/main/docs/data-types.md>  
**Updated:** 2026-05-12
