fix: dropped frames fail the run instead of printing a footer

A drop was reported to stderr and the process exited 0, so a run that discarded
320 frames "succeeded" and produced a truth file that looked complete. The
output in that case is a claim about footage that was never analysed, and
nothing in the file says so.

Now exits 2 and says why. Distinct from 1 (node crash) because the failures are
different: a crash produced no output, a drop produced output that cannot be
trusted.

This is also the regression test for AR-004 that otherwise did not exist. The
backpressure fix is one line in the KPN submodule — easy to lose in an update —
and with data pushes blocking, a drop can no longer occur on the data path. So
any drop now means either that fix regressed or a channel was disabled mid-run,
and both are worth stopping for.

Verified: a clean run still exits 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

TRACES: AR-004 | SR-002
This commit is contained in:
2026-07-31 10:45:39 +02:00
co-authored by Claude Opus 5
parent b5c7d4f6d9
commit c36885de73
+17 -2
View File
@@ -282,15 +282,30 @@ int main(int argc, char** argv) {
net.stop(); net.stop();
net.print_diagnostics(); net.print_diagnostics();
/// TRACES: AR-004 | SR-002
// A dropped frame does not degrade a result, it silently changes one —
// the output is a claim about footage that was never analysed, and
// nothing in the file says so. Since AR-004 made data pushes block, a
// drop can no longer happen on the data path, so any drop here means
// either that fix regressed (it lives in the KPN submodule, one line,
// easy to lose in an update) or a channel was disabled mid-run.
//
// Reporting it in a footer and exiting 0 made both invisible: the run
// "succeeded" and the truth file looked complete. Fail instead.
bool dropped = false;
{ {
std::lock_guard<std::mutex> lk(event_mtx); std::lock_guard<std::mutex> lk(event_mtx);
if (!overflow_counts.empty()) { if (!overflow_counts.empty()) {
std::cerr << "[main] dropped frames (channel overflow):\n"; dropped = true;
std::cerr << "[main] ERROR: frames were dropped (channel overflow):\n";
for (const auto& [name, count] : overflow_counts) for (const auto& [name, count] : overflow_counts)
std::cerr << " " << name << ": " << count << "\n"; std::cerr << " " << name << ": " << count << "\n";
std::cerr << "[main] The output would describe footage that was never "
"analysed. Refusing to report success.\n";
} }
} }
return node_crashed.load(std::memory_order_acquire) ? 1 : 0; if (node_crashed.load(std::memory_order_acquire)) return 1;
return dropped ? 2 : 0;
}; };
// ── Build static network and run ────────────────────────────────────────── // ── Build static network and run ──────────────────────────────────────────