Cluster faces into people, and calibrate what a similarity means

FR-CULL-9 forbids thresholding a bare cosine anywhere in the subsystem,
so calibrate fits P(same person) per library and reports whether the fit
is trustworthy. Two details carry most of the weight.

The fit runs against a 200-bin histogram rather than a pair list: a
25,000-face library has ~3e8 pairs and no gradient descent is running
over that. And a fresh library has no valid calibration, because the
positives have to come from user confirmations or burst siblings --
bootstrapping them from high cosine would fit the calibration to the
belief it was supposed to test.

Clustering defends against the over-merging FR-CULL-10 warns about with
constraints rather than a better threshold: two faces in one photograph
never merge, and two groups confirmed as different people never merge.
Average link rather than single link, so one strong edge cannot weld two
families together.

Calibration is defined once, in dr-face, and dr-catalog re-exports it.
Two implementations of one probability model is exactly how a number
comes to mean the wrong thing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-26 20:10:33 +02:00
co-authored by Claude Opus 5
parent aac3136407
commit 00e78dc2ac
9 changed files with 929 additions and 52 deletions
+23
View File
@@ -760,6 +760,29 @@ scalar letterbox resample in front of it.
Steps 1–5 are the spike. Steps 6–8 are the build, and they are only justified if §12 says so.
### 13.1 Where this had got to · 2026-08-26
- **1 — done.** M1 passes conditionally; §12.1.
- **2 — outstanding.** §2.3's three questions are unanswered and gate *shipping*, not building.
- **3 — done.** `core/dr-face`: `align`, `detect`, `embed`, `embedding`, and `examples/faces.rs`.
§12.2 is its first end-to-end run.
- **4 — partly.** M2/M3 have provisional numbers; M4/M5 need the labelled corpus.
- **5 — built, not yet measured.** `calibrate` and `cluster` exist with 34 model-free tests behind
them; M6–M8 are a run over a real library, which is what the corpus in §1.1's `images/` is for.
- **6 — done for storage.** Catalog schema v8 — `people`, `faces`, `face_person`,
`face_person_rejected`, `face_calibration` — with the identity operations FR-CULL-10 requires.
The `DetectFaces` job kind and the debounced clustering pass are not wired yet.
- **7, 8 — not started.** The People/Identity screen, and the route-C first-run flow.
Two things the build changed in this document's own design:
**`crop_px` reached the schema** as §7 argued it should, and the calibration carries a `w_size` term
for it.
**A rejection table was added**, which §8 and §9 did not contemplate. Rejection is not the absence of
an assignment: without storing it, the next clustering pass re-suggests exactly the face the user
just pushed away. It is user data in the same sense a confirmation is (FR-CULL-12), just negative.
---
## 14. What this does not settle
+1 -1
View File
@@ -9,7 +9,7 @@ Denominators are parsed from [`requirements.md`](requirements.md) at run time, n
| Metric | Value |
|---|---|
| Source files scanned | 235 |
| Source files scanned | 237 |
| TRACES tags found | 623 |
| Requirements defined | 177 |
| Requirements covered | 97 |