ci: make both workflows able to run at all #1

Merged
dtourolle merged 6 commits from ci/green-the-runner into master 2026-09-03 18:19:42 +00:00
2 changed files with 41 additions and 12 deletions
Showing only changes of commit 3966e19a83 - Show all commits
+7
View File
@@ -192,6 +192,13 @@ TEST_CASE("a track within the extinction window is still a candidate",
Embedding person = at_sim(0, 1, 0.99f);
int id_pre = r.track_of(frame(0.0, 10, 10, person));
// Identify it while it is still on screen. Since 1477c53 a DORMANT track is
// only associable if it was owned -- an anonymous one has no actor to
// re-attach to, so it is dropped from the pool a line before the horizon is
// ever consulted. Without this the test cannot reach what it is about.
r.reg->observe(id_pre, /*actor=*/0, /*posterior=*/0.99f, person);
r.track_of(frame(1.0, 300, 300, axis(7), /*is_cut=*/true));
// Back inside the window: the same person continues the same track, so the
+34 -12
View File
@@ -415,15 +415,21 @@ TEST_CASE("a track is not reaped until the evidence clock passes it",
}
/// TRACES: UT-001 | AR-008, AR-013 | SR-002
TEST_CASE("a track retired from association is still open to evidence",
TEST_CASE("association and reaping retire a track on the same clock",
"[registry][AR-008]") {
// The two clocks answer different questions and must not share an answer.
// Association asks "may this detection link to that track?" on the tracker's
// clock; reaping asks "is that track finished?" and cannot answer until the
// votes are in. Deferring both to the evidence clock was the second half of
// this bug: retired tracks lingered in the candidate pool for as long as the
// matcher lagged, so a new face re-associated onto a long-dead track and two
// people merged into one window.
// Renamed and rewritten for the unified clock. This test used to assert the
// opposite arrangement -- association answered on the tracker's clock while
// reaping answered on the evidence watermark -- and it was written when that
// was true. It is not true now: candidates() and reap_locked() take the SAME
// clock and the SAME threshold, so "retired from association" and "reaped"
// are one event, and the interval the old name described does not exist.
//
// Both halves of the AR-013 bug are visible here. Offering on a LOOSER
// horizon than the reap left retired tracks in the candidate pool for as
// long as the matcher lagged, so a new face re-associated onto a long-dead
// track and two people merged into one window. Reaping on a looser horizon
// than the offer killed tracks whose votes were still in flight. One clock
// makes both unrepresentable.
TrackRegistry reg(cfg(/*extinction=*/5.0), disc());
Sink sink; sink.attach(reg);
reg.expect_evidence();
@@ -432,21 +438,37 @@ TEST_CASE("a track retired from association is still open to evidence",
{
auto s = reg.begin_frame(0.0);
id = s.create(0.0, axis(1));
}
// Owned before it goes dormant, for the reason above: an unidentified
// dormant track is not a candidate at any horizon (1477c53).
reg.observe(id, 7, 0.99f, axis(1));
{
auto s = reg.begin_frame(0.0);
s.mark_lost(id, 0.0);
}
{
auto s = reg.begin_frame(3.0); // inside the window
auto s = reg.begin_frame(3.0); // watermark inside the window
CHECK(s.candidates().size() == 1); // still associable
}
// The tracker races far past the horizon while the matcher lags. This
// retires nothing, and that is the point of the watermark: the clock that
// decides has not moved, so the track is still offered.
{
auto s = reg.begin_frame(50.0); // far outside it
CHECK(s.candidates().empty()); // retired from association...
auto s = reg.begin_frame(50.0);
CHECK(s.candidates().size() == 1);
}
// ...but not gone, and still able to receive the votes in flight for it.
// Which is what keeps it able to receive the votes still in flight for it.
reg.observe(id, 7, 0.99f, axis(1));
CHECK(reg.dropped_votes() == 0);
// Only the watermark passing last_seen + extinction retires it -- and the
// same call reaps and emits it, so there is no interval in between.
reg.advance_evidence(50.0);
{
auto s = reg.begin_frame(50.0);
CHECK(s.candidates().empty());
}
REQUIRE(sink.claims.size() == 1);
CHECK(sink.claims[0].actor_idx == 7);
}