diff --git a/src/nodes/face_aligner_node.hpp b/src/nodes/face_aligner_node.hpp index a684b1a..f14cda4 100644 --- a/src/nodes/face_aligner_node.hpp +++ b/src/nodes/face_aligner_node.hpp @@ -4,12 +4,16 @@ #include // ── FaceAlignerFunc ─────────────────────────────────────────────────────────── +/// TRACES: AR-005, AR-030 | SR-002 +/// // KPN node: applies a 5-point similarity transform to each detected face, // producing a 112×112 BGR crop suitable for ArcFace inference. // -// Alignment uses cv::estimateAffinePartial2D (RANSAC) to fit the detected -// landmarks to ArcFace canonical positions. Degenerate detections (where the -// affine fit fails) are silently dropped from the output vectors. +// Alignment is an Umeyama least-squares fit over all five landmarks (AR-005), +// not a robust one: a RANSAC fit discards the very landmarks AR-030 reads. +// Degenerate detections (where the fit fails) are dropped from the output +// vectors. The fit's residual is the AR-030 visibility measure and comes free, +// since the warp needs the transform anyway. struct FaceAlignerFunc { static constexpr std::string_view label() { return "face_aligner"; } diff --git a/tests/test_calibration.cpp b/tests/test_calibration.cpp index 8728f9e..2b92434 100644 --- a/tests/test_calibration.cpp +++ b/tests/test_calibration.cpp @@ -1,6 +1,12 @@ +// TRACES: AR-023 | SR-002 +// // Unit tests for gallery calibration: the sigmoid math, the pairwise fit on // separable data, and the in-memory hash-keyed cache (hit / stale / cold). // All pure, GPU-free, model-free. +// +// The three `[report]` cases at the bottom carry their own GR-003 tags: they +// verify the build report, which is fitted from the same distributions but is a +// separate requirement. #include #include @@ -183,6 +189,7 @@ Embedding unit_axis(int slot) { } } // namespace +// TRACES: GR-003 | SR-001 TEST_CASE("report surfaces actors that can never be recognised", "[report][GR-003]") { // An actor with no usable image is a silent recall ceiling: the pipeline // will never name them, and nothing in the gallery says why. This is the @@ -212,6 +219,7 @@ TEST_CASE("report surfaces actors that can never be recognised", "[report][GR-00 CHECK(r.actors[1].references == 0); } +// TRACES: GR-003 | SR-001 TEST_CASE("report surfaces actors too thin to calibrate on", "[report][GR-003]") { // Below the positive-pair threshold an actor contributes nothing to the // intra-class side of the fit. They are not broken, so nothing complains — @@ -237,6 +245,7 @@ TEST_CASE("report surfaces actors too thin to calibrate on", "[report][GR-003]") CHECK(r.actors_below_positive_threshold >= 1); } +// TRACES: GR-003 | SR-001 TEST_CASE("report round-trips", "[report][GR-003]") { ActorGallery g; ActorGallery::Actor act; diff --git a/tests/test_face_tracker.cpp b/tests/test_face_tracker.cpp index 26b2c82..c0645bf 100644 --- a/tests/test_face_tracker.cpp +++ b/tests/test_face_tracker.cpp @@ -1,13 +1,17 @@ +// TRACES: AR-007, AR-008 | SR-002 +// // Unit tests for FaceTrackerFunc (nodes/face_tracker_node.hpp): frame-to-frame // track linking and, crucially, cross-cut re-association. Pure, GPU-free, // model-free — drives the node's operator() with hand-built EmbeddedSceneFrames // and inspects the emitted track_ids. // -// The behaviour under test: on a camera-angle change (Frame::is_cut) the tracker -// parks its tracks instead of destroying them, and revives a parked track_id -// when a post-cut detection's raw last-frame-embedding cosine similarity clears -// cut_revive_sim. IoU is deliberately driven to 0 across the cut (boxes moved) so -// only the embedding path can re-link — exactly the scenario a cut creates. +// The behaviour under test: there is one track pool keyed on `last_seen` +// (AR-008), so a face lost across a camera-angle change (Frame::is_cut) is an +// ordinary association candidate rather than a parked track needing a revival +// path — the raw-cosine `cut_revive_sim` that guarded that path is retired +// (AR-024). On a cut the association weight drops to embedding-only (AR-007), +// and IoU is deliberately driven to 0 across the cut (boxes moved) so only the +// embedding path can re-link — exactly the scenario a cut creates. #include #include "config.hpp" diff --git a/tests/test_similarity.cpp b/tests/test_similarity.cpp index 14d2bc3..b508077 100644 --- a/tests/test_similarity.cpp +++ b/tests/test_similarity.cpp @@ -1,5 +1,11 @@ +// TRACES: AR-026 | SR-001 +// // Unit tests for the CPU reference similarity engine (backends/gemm_backend.cpp, // SAE_GEMM_CPU) and the l2_normalise helper. All pure, GPU-free, model-free. +// +// This is the CI half of AR-026: equivalence between the GEMM path and +// hand-computed dot products on small input. Throughput at scale (AR-027) is T4 +// and cannot run here. #include #include