Run the formatter over the face branch before it reaches CI
🐳 Android image / Build and push (push) Successful in 2s
Build and test / android-image (push) Successful in 2s
Build and test / Desktop (Linux) (push) Successful in 1h21m32s
Build and test / Layer separation (push) Successful in 37s
Traceability / Requirement traces (push) Successful in 25s
Build and test / Android (aarch64) (push) Failing after 33m58s

The merge of the SCRFD/MobileFaceNet work brought 69 rustfmt diffs across
dr-catalog, dr-face and dr-ui with it, so `cargo fmt --all -- --check` fails
on master and the Desktop job stops at its Format step — before clippy, the
tests or the release build have run at all. That makes the whole desktop
half of CI blind: a real compile error behind this would look exactly the
same from the outside. There was nothing behind it, as it turns out — with
the formatting fixed, clippy, the test suite and the release build all pass.

Every .rs hunk is `cargo fmt --all` on the pinned 1.92.0 toolchain, not a
hand edit, but it is worth being precise about what that moved, because it
is more than whitespace. Besides reflowing signatures and call chains,
rustfmt reordered the `pub mod` and `pub use` items in dr-face/src/lib.rs so
the `#[cfg(feature = "inference")]` entries sort in place, added the trailing
semicolon inside `let ... else { return }` bodies in identity_ui.rs, wrapped
a bare closure body in braces in cluster.rs, adjusted trailing commas, and
dropped a stray blank line at the end of identity_ui.rs. All of it is
semantically inert; none of it changes behaviour.

docs/traceability.md rides along because it has to. The matrix records each
TRACES tag by line number, and reflowing develop.rs, lib.rs, faces.rs,
identity.rs and identity_ui.rs moved them — FR-CAT-8, FR-CAT-9, FR-CULL-10,
FR-DEV-3, FR-DEV-3a and FR-DEV-3c all shift by a line or two. The matrix was
verified up to date on d777f7f before this commit, so this is drift these
formatting changes introduced, not pre-existing staleness being swept up.
Leaving it for a follow-up commit would hand traceability-check.yml a
failure caused entirely by a whitespace change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 13:12:49 +02:00
co-authored by Claude Opus 5
parent d777f7f44d
commit b846b312b8
18 changed files with 285 additions and 207 deletions
+62 -28
View File
@@ -61,7 +61,10 @@ impl PersonRow {
/// — the exact conflation the confirmed/suggested split exists to prevent.
pub fn display_name(&self) -> String {
if self.name.is_empty() {
format!("Unnamed ({} faces)", self.confirmed_faces + self.suggested_faces)
format!(
"Unnamed ({} faces)",
self.confirmed_faces + self.suggested_faces
)
} else {
self.name.clone()
}
@@ -122,7 +125,10 @@ pub struct IdentityView {
}
/// Read the people rail.
pub fn load_people(catalog: &Catalog, model_id: &str) -> Result<IdentityView, dr_catalog::CatalogError> {
pub fn load_people(
catalog: &Catalog,
model_id: &str,
) -> Result<IdentityView, dr_catalog::CatalogError> {
let conn = catalog.connection();
let people = faces::people(conn)?
.into_iter()
@@ -410,10 +416,7 @@ pub fn rename(
/// The operation the screen exists to make cheap. A cluster that is simply
/// right — the common case for a well-photographed person — should cost one
/// click, not forty.
pub fn confirm_all(
catalog: &Catalog,
person: PersonId,
) -> Result<usize, dr_catalog::CatalogError> {
pub fn confirm_all(catalog: &Catalog, person: PersonId) -> Result<usize, dr_catalog::CatalogError> {
let conn = catalog.connection();
let mut n = 0;
for f in faces::for_person(conn, person, true)? {
@@ -662,7 +665,8 @@ mod tests {
let c = catalog();
let i1 = image(&c, 1);
let i2 = image(&c, 2);
let a = faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let a =
faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
faces::record_detections(c.connection(), i2, "w600k_mbf", 1024, &[face(2)]).unwrap();
let anna = faces::create_person(c.connection(), "Anna").unwrap();
@@ -672,7 +676,10 @@ mod tests {
assert_eq!(view.people.len(), 1);
assert_eq!(view.people[0].name, "Anna");
assert_eq!(view.unassigned, 1);
assert!(!view.calibrated, "a fresh library has no fitted calibration");
assert!(
!view.calibrated,
"a fresh library has no fitted calibration"
);
}
#[test]
@@ -681,9 +688,12 @@ mod tests {
let i1 = image(&c, 1);
let i2 = image(&c, 2);
let i3 = image(&c, 3);
let a = faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let b = faces::record_detections(c.connection(), i2, "w600k_mbf", 1024, &[face(2)]).unwrap();
let d = faces::record_detections(c.connection(), i3, "w600k_mbf", 1024, &[face(3)]).unwrap();
let a =
faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let b =
faces::record_detections(c.connection(), i2, "w600k_mbf", 1024, &[face(2)]).unwrap();
let d =
faces::record_detections(c.connection(), i3, "w600k_mbf", 1024, &[face(3)]).unwrap();
let anna = faces::create_person(c.connection(), "Anna").unwrap();
faces::confirm(c.connection(), a[0], anna).unwrap();
@@ -692,7 +702,12 @@ mod tests {
assert_eq!(confirm_all(&c, anna).unwrap(), 2);
assert_eq!(confirm_all(&c, anna).unwrap(), 0, "should be idempotent");
assert_eq!(faces::for_person(c.connection(), anna, false).unwrap().len(), 3);
assert_eq!(
faces::for_person(c.connection(), anna, false)
.unwrap()
.len(),
3
);
}
/// The correction must stick. Splitting a face off and then re-running
@@ -702,16 +717,24 @@ mod tests {
let c = catalog();
let i1 = image(&c, 1);
let i2 = image(&c, 2);
let a = faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let b = faces::record_detections(c.connection(), i2, "w600k_mbf", 1024, &[face(2)]).unwrap();
let a =
faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let b =
faces::record_detections(c.connection(), i2, "w600k_mbf", 1024, &[face(2)]).unwrap();
let anna = faces::create_person(c.connection(), "Anna").unwrap();
faces::confirm(c.connection(), a[0], anna).unwrap();
faces::suggest(c.connection(), b[0], anna, 0.95).unwrap();
let bob = split_off(&c, anna, &[b[0]], "Bob").unwrap();
assert_eq!(faces::for_person(c.connection(), bob, false).unwrap().len(), 1);
assert_eq!(faces::for_person(c.connection(), anna, true).unwrap().len(), 1);
assert_eq!(
faces::for_person(c.connection(), bob, false).unwrap().len(),
1
);
assert_eq!(
faces::for_person(c.connection(), anna, true).unwrap().len(),
1
);
// The next clustering pass tries again and is refused.
assert!(
@@ -735,8 +758,10 @@ mod tests {
let c = catalog();
let i1 = image(&c, 1);
let i2 = image(&c, 2);
let a = faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let b = faces::record_detections(c.connection(), i2, "w600k_mbf", 1024, &[face(2)]).unwrap();
let a =
faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let b =
faces::record_detections(c.connection(), i2, "w600k_mbf", 1024, &[face(2)]).unwrap();
let anna = faces::create_person(c.connection(), "Anna").unwrap();
let annie = faces::create_person(c.connection(), "Annie").unwrap();
faces::confirm(c.connection(), a[0], anna).unwrap();
@@ -752,8 +777,8 @@ mod tests {
fn named_boxes_come_back_in_proxy_pixels() {
let c = catalog();
let img = image(&c, 1);
let ids = faces::record_detections(c.connection(), img, "w600k_mbf", 1024, &[face(1)])
.unwrap();
let ids =
faces::record_detections(c.connection(), img, "w600k_mbf", 1024, &[face(1)]).unwrap();
let anna = faces::create_person(c.connection(), "Anna").unwrap();
faces::confirm(c.connection(), ids[0], anna).unwrap();
@@ -777,12 +802,14 @@ mod tests {
fn a_suggested_person_does_not_name_a_region() {
let c = catalog();
let img = image(&c, 1);
let ids = faces::record_detections(c.connection(), img, "w600k_mbf", 1024, &[face(1)])
.unwrap();
let ids =
faces::record_detections(c.connection(), img, "w600k_mbf", 1024, &[face(1)]).unwrap();
let anna = faces::create_person(c.connection(), "Anna").unwrap();
faces::suggest(c.connection(), ids[0], anna, 0.95).unwrap();
assert!(named_boxes_for_image(&c, img, 1024, 683).unwrap().is_empty());
assert!(named_boxes_for_image(&c, img, 1024, 683)
.unwrap()
.is_empty());
// Confirming it makes the name appear.
faces::confirm(c.connection(), ids[0], anna).unwrap();
@@ -794,12 +821,14 @@ mod tests {
fn an_unnamed_group_does_not_name_a_region() {
let c = catalog();
let img = image(&c, 1);
let ids = faces::record_detections(c.connection(), img, "w600k_mbf", 1024, &[face(1)])
.unwrap();
let ids =
faces::record_detections(c.connection(), img, "w600k_mbf", 1024, &[face(1)]).unwrap();
let nameless = faces::create_person(c.connection(), "").unwrap();
faces::confirm(c.connection(), ids[0], nameless).unwrap();
assert!(named_boxes_for_image(&c, img, 1024, 683).unwrap().is_empty());
assert!(named_boxes_for_image(&c, img, 1024, 683)
.unwrap()
.is_empty());
}
#[test]
@@ -817,7 +846,11 @@ mod tests {
height: 4,
rgba,
};
assert!((mean_luma(&crop) - 1.0).abs() < 1e-3, "{}", mean_luma(&crop));
assert!(
(mean_luma(&crop) - 1.0).abs() < 1e-3,
"{}",
mean_luma(&crop)
);
}
#[test]
@@ -835,7 +868,8 @@ mod tests {
fn deleting_everything_empties_the_screen() {
let c = catalog();
let i1 = image(&c, 1);
let a = faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let a =
faces::record_detections(c.connection(), i1, "w600k_mbf", 1024, &[face(1)]).unwrap();
let anna = faces::create_person(c.connection(), "Anna").unwrap();
faces::confirm(c.connection(), a[0], anna).unwrap();