exocortex-dreams 0.1.0

Exocortex consolidation engine: MCR-squared rate reduction, graph-sparsity guardrails, rollback, and structured discovery proposals.
# Clustering decision (M8 task 3, §12.5)

**Chosen: vendored HDBSCAN-style single-linkage over mutual-reachability
distances is DEFERRED; v1 ships deterministic agglomerative clustering with
a fixed cosine-distance threshold (a "DBSCAN-lite" with min_pts=2).**

## Evaluation

### linfa-clustering (DBSCAN)
- Not in the §2.2 dependency catalog; pulling it would add `linfa`,
  `ndarray`, `ndarray-stats`, and their transitive trees to the workspace —
  a new-dependency decision the PRD reserves for recorded exceptions.
- `linfa` pre-0.8 crates had MSRV drift; on the pinned Rust 1.85 toolchain
  the resolved versions were untested.
- API is synchronous CPU work; Dreams wants async-friendly, region-bounded
  batches. Workable, but the dependency cost is the blocker.

### Vendored HDBSCAN
- Correct HDBSCAN needs: kNN graph (O(n log n)), mutual-reachability,
  minimum-spanning tree (Boruvka/Prim), condensed cluster tree, and excess-
  of-mass extraction. That is a multi-week numerical-code project with its
  own test burden — beyond "vendored" in any honest sense.
- v1's Dreams cycle needs *deterministic cluster ids for merge candidates*,
  which full HDBSCAN does not directly provide (its stability extraction
  gives a hierarchy, not stable labels).

### Shipped: threshold clustering (deterministic, dependency-free)
- Anchors within `merge_threshold` cosine distance (default 0.92 similarity,
  §12.5 step 5) join the same cluster; every anchor gets a cluster id or
  `NOISE` deterministically by (similarity desc, memory id asc) ordering.
- Assigns every anchor to a cluster id (or noise) deterministically — the
  M8 acceptance property — and it is what merge detection needs anyway
  (near-duplicates share a cluster).
- The §12.1 pipeline references HDBSCAN as the target clustering; this file
  records that v1 ships the threshold approximation and that the full
  algorithm (or linfa once the dependency is justified) is the v2 upgrade.

## Why this satisfies the milestone
§3 M8 task 3 requires: "whichever is chosen must assign every anchor to a
cluster id (or noise) deterministically." The threshold clusterer does
exactly that, with zero new dependencies (CR-26-friendly), and the merge
step that consumes it is the actual value carrier of the cycle.