Say what actually counts as a rival, now that a name anchors too

assign's denominator is the identities the user has ruled on, and it
reads Cluster::person to find them. Master's "Let a name hold a group
together" widened what sets that field: a confirmation, a name, or an
ignore, where before it was a confirmation alone.

The behaviour is right either way — a named person is exactly the
identity a suggestion should be discounted against — but the module note
and faces.md §9.1 both said "a confirmation", which is now too narrow.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-29 12:32:31 +02:00
co-authored by Claude Opus 5
parent da20d42d33
commit 39c34d4e44
2 changed files with 13 additions and 10 deletions
+9 -7
View File
@@ -58,9 +58,10 @@
//! and the better covered the person, the more fragments there are to lose to. //! and the better covered the person, the more fragments there are to lose to.
//! //!
//! A fragment is not a rival. An identity the user has actually asserted is, so //! A fragment is not a rival. An identity the user has actually asserted is, so
//! the denominator counts only people a confirmation names ([`Cluster::person`]) //! the denominator counts only the people they have ruled on — a group carries
//! — and counts them **per person, not per group**, since a named person is //! a [`Cluster::person`] when it holds a confirmation, a name, or an ignore —
//! left in several anchored groups for the same reason. Keying it by group had //! and counts them **per person, not per group**, since one person is left in
//! several anchored groups for the same reason. Keying it by group had
//! Catherine competing with Catherine and put the median suggestion onto a //! Catherine competing with Catherine and put the median suggestion onto a
//! named person at 39%; keying it by person put it at 99.5%. //! named person at 39%; keying it by person put it at 99.5%.
//! //!
@@ -209,10 +210,11 @@ pub fn identity_shares(faces: usize, clusters: &[Cluster], pairs: &[Pair], top:
ours = score; ours = score;
coherence = score / counted as f32; coherence = score / counted as f32;
} else if matches!(who, Identity::Person(_)) { } else if matches!(who, Identity::Person(_)) {
// Only an identity the user has asserted competes. An unnamed // Only an identity the user has ruled on competes. A group
// group that matches this face is far more likely to be another // nobody has ruled on and that matches this face is far more
// fragment of the same person than a different one — see the // likely to be another fragment of the same person than a
// module note, and the library it was measured on. // different one — see the module note, and the library it was
// measured on.
rivals += score; rivals += score;
} }
} }
+4 -3
View File
@@ -758,9 +758,10 @@ equally well land at 0.5 each, which is the truth about a sibling.
**Only named people compete, and they compete per person.** This is the part that had to be measured **Only named people compete, and they compete per person.** This is the part that had to be measured
rather than reasoned about. Normalising across *every* group made the number useless on a real rather than reasoned about. Normalising across *every* group made the number useless on a real
18,000-face library — median suggestion 21%, four in five under half — because clustering leaves one 18,000-face library — median suggestion 21%, four in five under half — because clustering leaves one
person spread across many groups, so a face competes against itself. Counting only groups holding a person spread across many groups, so a face competes against itself. Counting only the groups the user has
confirmation fixed most of it; counting them **per person** rather than per group fixed the rest, ruled on — one holding a confirmation, a name, or an ignore — fixed most of it; counting them **per
since a named person is left in several anchored groups for the same reason. person** rather than per group fixed the rest, since one person is left in several anchored groups
for the same reason.
**Rivals are gathered below the merge threshold**, down to even odds: a named person who matches at **Rivals are gathered below the merge threshold**, down to even odds: a named person who matches at
0.6 will never be merged into but is exactly the competition a suggestion should be discounted for. 0.6 will never be merged into but is exactly the competition a suggestion should be discounted for.