polydigest 0.1.0

Polydigest combinator — lifts the Merkle Spine across N algorithms over one shared substrate: the activation timeline, null-run-extents, the binding root, coupling, and the bound snapshot.
Documentation
# polydigest — the combinator

**Tier L3 — the combinator over a shared data substrate.** `polydigest` lifts a
single-algorithm canonical-ml log or canonical-mt tree across **N algorithms over 
one shared data substrate**. It depends on canonical-ml and canonical-mt (which 
depend on `merkle-spine`); the instantiations `eml` / `emt` depend on it.

## Role

`polydigest` is **not** a composition of independent logs — that would duplicate the data
and raise per-algorithm cost. It is a combinator over **one** substrate: the leaf
entries live once, and each algorithm is a frontier / hash-view over them, so its
only per-algorithm cost is its own hashing. The append-only driver
(`NaryMerkleLog`) holds the shared store plus, per algorithm, a `{hasher, frontier}`
view; its mutable peer is `EpochTree` (`polydigest(cmt)`), the same combinator lifting a
`cmt::Cmt`.

It adds the three concepts the structural core (`spine`) deliberately omits:

- **The activation timeline** — the committed epochs that say which algorithm is
  live where (`validate_committed_epochs`, `committed_active_at`,
  `committed_active_algs`).
- **The null-run-extents** — the one logical count, the per-tree-divergent collapse
  (`NullRun`, `null_runs_for_alg`, `serialize_null_runs`). It is the only quantity
  ever counted in the whole stack, retained solely for cross-tree alignment.
- **The binding root** — the atomic multi-tree commitment (`combined_root`), the same
  canonicalization fold applied one level up over the per-algorithm member roots as
  opaque children. It is opened by a `CouplingProof` and proven mutually consistent
  by a `BindingProof`. Member roots enter as opaque digests, so no algorithm's break
  weakens another.

## Snapshots and filling

The combinator's frozen snapshot is `Sealed` — the `BoundSnapshot` epoch facet over
a structural `spine::Seal`; the structural `Seal` carries no epoch field. The `fill`
operation (trustless rebuild over the real leaf data, verified against the committed
binding root) and the aggregate `SnapshotProof` are the verification surfaces over a
`Sealed`.

## Non-regression invariant

The combinator must not make any one algorithm more expensive or more complex:
atomic multi-tree commit is preserved via the binding root, and one shared substrate
with a per-algorithm frontier only means no data duplication and no per-algorithm
cost increase.

## Place in the layered model

```
merkle-spine — the structural core
  │
  ├── canonical-ml (append-only)   canonical-mt (mutable)
  │        ╲             ╱
  │      polydigest  ◄── this crate (the combinator)
  │         │
  │       EML / EMT  (k=2 instantiations)
```

## Further reading

- `canonical-ml` / `canonical-mt` — the single-algorithm engines this combinator drives.
- `eml` / `emt` — the concrete instantiations at `k = 2`.
- [`../docs/architecture.md`]../docs/architecture.md — the full design.