# WP2-006 — Rehydration

## Scope

WP2-006 adds read-side reconstruction for the two persistence aggregate roots introduced in WP2-005:

- `SourceValueRepository::findById()`
- `ReconciliationResultRepository::findById()`

The relational repositories coordinate specialized data mappers. Each mapper reconstructs only its own Domain type; repositories assemble and validate complete aggregates.

## Implemented

### SourceValue aggregate

- `SourceValueMapper::findById()`
- `InterpretationGraphMapper::findBySourceValueId()`
- `InterpretationNodeMapper::findByGraphId()`
- aggregate assembly in `RelationalSourceValueRepository`

### ReconciliationResult aggregate

- `ReconciliationResultMapper::findById()`
- `CandidateItemMapper::findByResultId()`
- `MatchDecisionMapper::findByResultId()`
- restoration of selected candidate URI through a relational join
- aggregate assembly in `RelationalReconciliationResultRepository`

### JSON values

`JsonValueDecoder` restores persisted `provenance_json` and `payload_json` values. Invalid JSON is translated to `PersistenceException`.

## Semantics

- `findById()` returns `null` when the aggregate root does not exist.
- IDs must be positive.
- Domain constructors enforce invariants during reconstruction.
- Inconsistent subordinate rows fail with `PersistenceException`; no partial aggregate is returned.
- The current Domain Model still supports exactly one `InterpretationGraph` per `SourceValue` and exactly one root node per graph.

## Out of scope

- cross-repository transaction coordination
- Identity Map
- Unit of Work
- lazy loading
- caching
- ORM

These remain outside WP2-006; transaction coordination belongs to WP2-007.

## Tests

Run:

```bash
php tests/Persistence/RehydrationTest.php
```

The test covers both aggregate reconstructions, technical IDs, JSON decoding, and restoration of the selected Candidate URI.
