Withhold the empty groups that fill the People rail
`load_people` returned every live person, and on the reference library that was 14,268 rows of which 11,739 held no faces at all — 85 per cent of the rail naming nobody and able to do nothing. They are not a mystery. A regrouping pass creates a person per cluster; the next pass moves those faces elsewhere and leaves the person it emptied behind. `faces::prune_empty_unnamed` exists for exactly this and runs only at the end of a pass, so nothing clears what accumulates between them, and the Identity screen never prunes at all. Each one cost a `for_person` query and a built row on every reload. This withholds precisely the set the prune already treats as disposable — empty, unnamed, not set aside — and no more. Filtered rather than deleted: a screen is being drawn, not a catalog repaired. Nothing is lost, a sync cannot resurrect what was never removed, and the prune stays the one place that decides these can go. An empty group with a *name* still shows. That one is not debris but the symptom of a real failure — a named person whose faces were regrouped out from under them — and hiding it would take away the only way to merge them back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -34,7 +34,7 @@ A face is either the system's guess or the user's judgement, and the two are nev
|
||||
|
||||
This is the point of having identified anybody. Without it the screen is a filing cabinet with no drawer handles.
|
||||
|
||||
<sub>`ui/dr-ui/ui/identity.slint:552`</sub>
|
||||
<sub>`ui/dr-ui/ui/identity.slint:571`</sub>
|
||||
|
||||
### Change how faces are grouped
|
||||
|
||||
@@ -43,7 +43,7 @@ This is the point of having identified anybody. Without it the screen is a filin
|
||||
|
||||
The right match confidence is a property of your library, not of the model. "What would this do?" answers for this library without writing anything; names, confirmations and the groups you have set aside are kept whatever the dials say.
|
||||
|
||||
<sub>`ui/dr-ui/ui/identity.slint:589`</sub>
|
||||
<sub>`ui/dr-ui/ui/identity.slint:608`</sub>
|
||||
|
||||
## Library grid
|
||||
|
||||
|
||||
@@ -156,6 +156,25 @@ pub struct IdentityView {
|
||||
}
|
||||
|
||||
/// Read the people rail.
|
||||
///
|
||||
/// **A group holding no faces is not a group, and does not appear.** Only the
|
||||
/// unnamed ones, which is exactly the set `faces::prune_empty_unnamed` treats
|
||||
/// as debris: a pass creates a person per cluster, the next pass regroups those
|
||||
/// faces elsewhere, and the person it emptied survives until something prunes
|
||||
/// it. Nothing prunes on this path, so they accumulate — the reference library
|
||||
/// reached 11,739 of them against 2,525 real people, and the rail was 85 per
|
||||
/// cent rows that named nobody and could do nothing.
|
||||
///
|
||||
/// Filtered rather than deleted, because this is a screen being drawn and not a
|
||||
/// catalog being repaired. A row is withheld; nothing is lost, a sync cannot
|
||||
/// resurrect what was never removed, and the prune stays the one place that
|
||||
/// decides these are disposable.
|
||||
///
|
||||
/// An empty group with a *name* still shows. That one is not debris, it is the
|
||||
/// symptom of a real failure — a named person whose faces were regrouped out
|
||||
/// from under them (see `Population::read` on why naming has to anchor) — and
|
||||
/// the user cannot merge it back into the group that took them if the rail has
|
||||
/// hidden it.
|
||||
pub fn load_people(
|
||||
catalog: &Catalog,
|
||||
model_id: &str,
|
||||
@@ -163,6 +182,9 @@ pub fn load_people(
|
||||
let conn = catalog.connection();
|
||||
let people = faces::people(conn)?
|
||||
.into_iter()
|
||||
.filter(|p| {
|
||||
p.confirmed_faces + p.suggested_faces > 0 || !p.name.trim().is_empty() || p.ignored
|
||||
})
|
||||
.map(|p| PersonRow {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
@@ -812,6 +834,53 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// The rail withholds the debris a regrouping pass leaves behind, and only
|
||||
/// that: the same rows `prune_empty_unnamed` treats as disposable.
|
||||
///
|
||||
/// Not a nicety. Every pass creates a person per cluster and the next pass
|
||||
/// may empty it, nothing on this path prunes, and the reference library
|
||||
/// reached 11,739 of them against 2,525 real people — a rail that was 85
|
||||
/// per cent rows naming nobody, each one costing a query and a built row.
|
||||
#[test]
|
||||
fn the_rail_withholds_empty_unnamed_groups_and_nothing_else() {
|
||||
let c = catalog();
|
||||
let i1 = image(&c, 1);
|
||||
let held =
|
||||
faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
|
||||
|
||||
let with_faces = faces::create_person(c.connection(), "Anna").unwrap();
|
||||
faces::confirm(c.connection(), held[0], with_faces).unwrap();
|
||||
|
||||
// The three that hold nothing. Only the first is debris.
|
||||
faces::create_person(c.connection(), "").unwrap();
|
||||
let named = faces::create_person(c.connection(), "Bob").unwrap();
|
||||
let set_aside = faces::create_person(c.connection(), "").unwrap();
|
||||
faces::set_ignored(c.connection(), set_aside, true).unwrap();
|
||||
|
||||
let shown: Vec<_> = load_people(&c, "w600k_mbf")
|
||||
.unwrap()
|
||||
.people
|
||||
.into_iter()
|
||||
.map(|p| p.id)
|
||||
.collect();
|
||||
|
||||
assert!(shown.contains(&with_faces), "a group with faces is a group");
|
||||
assert!(
|
||||
shown.contains(&named),
|
||||
"an empty group with a name is the visible symptom of a regroup that \
|
||||
emptied it, and hiding it takes away the only way to merge it back"
|
||||
);
|
||||
assert!(
|
||||
shown.contains(&set_aside),
|
||||
"set aside is a judgement the user made, and the prune spares it too"
|
||||
);
|
||||
assert_eq!(
|
||||
shown.len(),
|
||||
3,
|
||||
"the empty unnamed group is the one that goes"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn confirm_all_promotes_every_suggestion_and_nothing_else() {
|
||||
let c = catalog();
|
||||
|
||||
Reference in New Issue
Block a user