Make a sweep that fails everything say so

A run over 169 images failed all 169, in fourteen seconds, and reported
"0 face(s) in 0 image(s)" -- the same sentence a run that indexed
nothing because there was nothing to index produces. Three separate
places dropped the information on its way to the screen.

The progress count only moved on success. FaceSweepMessage had no
failure variant at all, so a pass where every image failed sat at 0/169
from the first tick to the last: the receiver was told the total, told
nothing, and told the pass had ended. That is indistinguishable from a
hung job, and it is what it was taken for.

Finished already carried a failed count and identity_ui matched it with
`Finished { .. }`, throwing the number away and printing the tidy
success line regardless.

And the reason each image failed was logged at debug, which is off, so
169 consecutive failures left no trace of why anywhere.

Failed { images } now carries the count back per lane batch, the
progress counter advances on it, and both the running status line and
the finishing activity row say how many could not be read. A batch
rather than one message per image because failures come back lane-sized
and the useful number is how many.

Also renames the store sweep's guard to MIN_CROP_EDGE with the rest of
that constant's move, since the two touch the same lines.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-30 19:41:20 +02:00
co-authored by Claude Opus 5
parent e7b526c550
commit 9ddc1273c0
3 changed files with 20 additions and 40 deletions
+8 -11
View File
@@ -163,18 +163,17 @@ fn main() {
// Say it here rather than letting the pass return an empty result and
// print "done: 0 image(s)". That is the shape of report this whole change
// exists to stop producing.
if faces::FACE_TIER.edge() < dr_face::MIN_DETECT_EDGE {
if faces::FACE_TIER.edge() < dr_face::MIN_CROP_EDGE {
println!(
"\n--run cannot index from the local store any more.\n\
\n\
Detection needs a proxy longer than {}px and the store's largest\n\
tier is {}px, so every image here would be refused. The measurement\n\
behind that floor is docs/faces.md §7c.\n\
Face crops must be sampled from a buffer longer than {}px and the\n\
store's largest tier is {}px, so every image here would be refused.\n\
The measurement behind that floor is docs/faces.md §7b.\n\
\n\
Index from the app's Identity screen instead: that pass fetches the\n\
embedded preview at full size, which is the resolution detection\n\
needs.",
dr_face::MIN_DETECT_EDGE - 1,
Index from the app's Identity screen instead: that pass renders at\n\
native resolution, which is what the crop needs.",
dr_face::MIN_CROP_EDGE - 1,
faces::FACE_TIER.edge(),
);
return;
@@ -214,11 +213,9 @@ fn main() {
images,
faces,
failed,
too_small,
} => {
println!(
"\ndone: {images} image(s), {faces} face(s), {failed} failed, \
{too_small} with no proxy big enough, in {:.0}s",
"\ndone: {images} image(s), {faces} face(s), {failed} failed, in {:.0}s",
start.elapsed().as_secs_f64()
);
}