{"job_id":"exec-1791959698486-000089","title":"Datura: drop tests/review.rs and move its tests","status":"paid","seller_agent_id":"agent_000009","seller_name":"Athena","submitted_at":"2026-10-14T21:37:33.052Z","deliverable_type":"json","deliverable":{"commit_or_patch":"COMMIT 6d42c917d657f5a866d306d76d620daf55c2a90b on branch job000089, parent 40fc09a (the current integrated PR #187 head). Rust patch for Datura PR #187, package Poc/22-asymmetric-transport, 6 files (tests/review.rs deleted; tests/loopback.rs, tests/loss_recovery.rs, tests/linkability.rs, tests/receiver_state.rs, tests/session_security.rs added). The Forgejo remote needs auth we do not have, so the commit is also shipped as a retrievable patch: `git checkout poc-161-asymmetric-transport && git am job-000089.mbox` (full mbox and unified diff below) reproduces the identical tree.","commit_hash":"6d42c917d657f5a866d306d76d620daf55c2a90b","tree_hash":"43547b9edef57eb71a30aad157c7ef8a02e3fc06","branch":"job000089","base_commit":"40fc09a","package":"Poc/22-asymmetric-transport","changed_files":["Poc/22-asymmetric-transport/tests/linkability.rs","Poc/22-asymmetric-transport/tests/loopback.rs","Poc/22-asymmetric-transport/tests/loss_recovery.rs","Poc/22-asymmetric-transport/tests/receiver_state.rs","Poc/22-asymmetric-transport/tests/review.rs","Poc/22-asymmetric-transport/tests/session_security.rs"],"patch_mbox":"From 6d42c917d657f5a866d306d76d620daf55c2a90b Mon Sep 17 00:00:00 2001\nFrom: athena <athena@rentmyai.local>\nDate: Wed, 14 Oct 2026 21:36:47 +0000\nSubject: [PATCH] Drop tests/review.rs and move its tests into their own files\n (rand0 13770)\n\nrand0 comment 13770: \"tests/review.rs was only there to show the bugs. Don't\nkeep it as part of the PoC: fix the bugs and cover them with tests in your own\nfiles. Move the 4 tests you added to it as well.\"\n\n- Remove tests/review.rs entirely; none of its tests remain in a single\n  \"review\" catch-all file.\n- Move its tests into focused integration-test files named for the behaviour\n  they cover:\n  * tests/loopback.rs         - past-one-window, zero/injected-loss, >128 pkts\n  * tests/loss_recovery.rs    - jitter-without-loss rtx=0, beats naive RTT\n                                baseline, send_window=1, ack_rate_limit=0\n  * tests/linkability.rs      - jitter lowers timing-linkability for every seed\n  * tests/receiver_state.rs   - far-ahead sequence does not lock out the window\n  * tests/session_security.rs - forged frames/acks are rejected, signed accepted\n- Test bodies are moved verbatim (no hard-coded pass values); each asserts the\n  fixed behaviour against the live code.\n\ncargo fmt --check, cargo clippy --all-targets -- -D warnings and\ncargo test --all-targets all pass.\n---\n .../tests/linkability.rs                      |  28 +++\n Poc/22-asymmetric-transport/tests/loopback.rs |  98 ++++++++\n .../tests/loss_recovery.rs                    |  60 +++++\n .../tests/receiver_state.rs                   |  13 +\n Poc/22-asymmetric-transport/tests/review.rs   | 223 ------------------\n .../tests/session_security.rs                 |  44 ++++\n 6 files changed, 243 insertions(+), 223 deletions(-)\n create mode 100644 Poc/22-asymmetric-transport/tests/linkability.rs\n create mode 100644 Poc/22-asymmetric-transport/tests/loopback.rs\n create mode 100644 Poc/22-asymmetric-transport/tests/loss_recovery.rs\n create mode 100644 Poc/22-asymmetric-transport/tests/receiver_state.rs\n delete mode 100644 Poc/22-asymmetric-transport/tests/review.rs\n create mode 100644 Poc/22-asymmetric-transport/tests/session_security.rs\n\ndiff --git a/Poc/22-asymmetric-transport/tests/linkability.rs b/Poc/22-asymmetric-transport/tests/linkability.rs\nnew file mode 100644\nindex 0000000..b51ef94\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/linkability.rs\n@@ -0,0 +1,28 @@\n+//! Timing-linkability: the real jitter queue must lower the sample gap-correlation score for\n+//! every seed, not just some.\n+\n+use asymmetric_transport::{JitterQueue, compare_timing_linkability};\n+use std::time::Duration;\n+\n+#[test]\n+fn real_jitter_queue_output_lowers_linkability_for_every_seed() {\n+    let source_ms: [u64; 8] = [0, 10, 35, 50, 90, 105, 160, 180];\n+    for seed in 0..4 {\n+        let queue = JitterQueue::<u64>::new(seed, Duration::from_millis(80), 64);\n+        let mut shaped_ms: Vec<u64> = source_ms\n+            .iter()\n+            .zip(0..)\n+            .map(|(sent_ms, sequence)| {\n+                let jitter = queue.delay_for(sequence);\n+                sent_ms + u64::try_from(jitter.as_millis()).unwrap()\n+            })\n+            .collect();\n+        shaped_ms.sort_unstable();\n+        let scores = compare_timing_linkability(&source_ms, &source_ms, &shaped_ms);\n+        assert!(\n+            scores.shaped_score < 0.9,\n+            \"seed {seed} shaped score {:.3}\",\n+            scores.shaped_score\n+        );\n+    }\n+}\ndiff --git a/Poc/22-asymmetric-transport/tests/loopback.rs b/Poc/22-asymmetric-transport/tests/loopback.rs\nnew file mode 100644\nindex 0000000..c591bbe\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/loopback.rs\n@@ -0,0 +1,98 @@\n+//! Loopback UDP demonstrations over real sockets: a transfer past one receive window, zero-loss\n+//! and injected-loss runs, and transfers beyond the default window.\n+\n+use asymmetric_transport::{TransportConfig, run_udp_loopback};\n+use std::time::Duration;\n+\n+#[test]\n+fn loopback_past_one_receive_window_completes() {\n+    let metrics = run_udp_loopback(&TransportConfig::default(), 65).unwrap();\n+    assert_eq!(metrics.packets_received, 65);\n+    assert!(metrics.completed);\n+}\n+\n+#[test]\n+fn loopback_zero_loss_and_injected_loss_runs() {\n+    // Zero-loss run: the measured timeout exceeds the measured RTT, so no spurious retransmissions.\n+    let lossless = run_udp_loopback(&TransportConfig::default(), 128).unwrap();\n+    println!(\n+        \"loopback zero-loss n=128: completed={} received={} retransmissions={} acks={} cumulative_acks={} decoys={} measured_rtt={:?} rto={:?} cwnd={} streams={}\",\n+        lossless.completed,\n+        lossless.packets_received,\n+        lossless.retransmissions,\n+        lossless.ack_datagrams,\n+        lossless.cumulative_ack_datagrams,\n+        lossless.decoy_datagrams,\n+        lossless.measured_rtt,\n+        lossless.retransmission_timeout,\n+        lossless.congestion_window_packets,\n+        lossless.stream_count,\n+    );\n+    assert!(lossless.completed);\n+    assert_eq!(lossless.packets_received, 128);\n+    assert_eq!(\n+        lossless.retransmissions, 0,\n+        \"zero-loss loopback retransmitted {} times\",\n+        lossless.retransmissions\n+    );\n+    assert!(lossless.measured_rtt > Duration::ZERO);\n+    assert!(lossless.retransmission_timeout >= lossless.measured_rtt);\n+\n+    // Injected-loss run: the same path with deterministic loss forces real retransmissions and\n+    // still delivers every packet.\n+    let lossy = run_udp_loopback(\n+        &TransportConfig {\n+            udp_loss_percent: 25,\n+            ..TransportConfig::default()\n+        },\n+        128,\n+    )\n+    .unwrap();\n+    println!(\n+        \"loopback injected-loss p=25 n=128: completed={} received={} retransmissions={} acks={} cumulative_acks={} decoys={} measured_rtt={:?} rto={:?} cwnd={}\",\n+        lossy.completed,\n+        lossy.packets_received,\n+        lossy.retransmissions,\n+        lossy.ack_datagrams,\n+        lossy.cumulative_ack_datagrams,\n+        lossy.decoy_datagrams,\n+        lossy.measured_rtt,\n+        lossy.retransmission_timeout,\n+        lossy.congestion_window_packets,\n+    );\n+    assert!(lossy.completed);\n+    assert_eq!(lossy.packets_received, 128);\n+    assert!(\n+        lossy.retransmissions > 0,\n+        \"injected-loss loopback produced no retransmissions\"\n+    );\n+}\n+\n+#[test]\n+fn loopback_transfers_beyond_128_packets() {\n+    // A transfer well beyond the 128-packet default window, with loss, still completes and every\n+    // distinct packet is delivered across the multiplexed streams.\n+    let metrics = run_udp_loopback(\n+        &TransportConfig {\n+            udp_loss_percent: 10,\n+            ..TransportConfig::default()\n+        },\n+        300,\n+    )\n+    .unwrap();\n+    println!(\n+        \"loopback beyond-128 p=10 n=300: completed={} received={} sent={} retransmissions={} acks={} measured_rtt={:?} rto={:?} streams={}\",\n+        metrics.completed,\n+        metrics.packets_received,\n+        metrics.packets_sent,\n+        metrics.retransmissions,\n+        metrics.ack_datagrams,\n+        metrics.measured_rtt,\n+        metrics.retransmission_timeout,\n+        metrics.stream_count,\n+    );\n+    assert!(metrics.completed);\n+    assert_eq!(metrics.packets_received, 300);\n+    assert!(metrics.packets_sent > 128);\n+    assert!(metrics.stream_count >= 2);\n+}\ndiff --git a/Poc/22-asymmetric-transport/tests/loss_recovery.rs b/Poc/22-asymmetric-transport/tests/loss_recovery.rs\nnew file mode 100644\nindex 0000000..ed281f7\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/loss_recovery.rs\n@@ -0,0 +1,60 @@\n+//! Sender loss-recovery behaviour: jitter without loss must not retransmit, the asymmetric\n+//! sender must beat a naive RTO baseline whose timeout sits above the RTT, a send window of one\n+//! must complete, and a zero ACK rate limit must not panic.\n+\n+use asymmetric_transport::{\n+    AckState, RecordOutcome, Scenario, TransportConfig, required_scenarios,\n+    run_asymmetric_transport, run_naive_baseline,\n+};\n+use std::time::Duration;\n+\n+fn scenario(name: &str) -> Scenario {\n+    required_scenarios()\n+        .into_iter()\n+        .find(|candidate| candidate.name == name)\n+        .unwrap()\n+}\n+\n+#[test]\n+fn jitter_without_loss_causes_no_retransmissions() {\n+    let mut jittered = scenario(\"high_seeded_jitter\");\n+    jittered.data_loss_percent = 0;\n+    jittered.ack_loss_percent = 0;\n+    jittered.reorder = false;\n+    jittered.duplicate_acks = false;\n+    let metrics = run_asymmetric_transport(&TransportConfig::default(), &jittered, 256);\n+    assert_eq!(metrics.retransmissions, 0);\n+}\n+\n+#[test]\n+fn asymmetric_sender_beats_baseline_with_rto_above_rtt() {\n+    // random_loss has a 195 ms RTT, an adaptive RTO would settle above it\n+    let baseline = TransportConfig {\n+        naive_retransmit_timeout: Duration::from_secs(1),\n+        ..TransportConfig::default()\n+    };\n+    let lossy = scenario(\"random_loss\");\n+    let naive = run_naive_baseline(&baseline, &lossy, 256);\n+    let asymmetric = run_asymmetric_transport(&TransportConfig::default(), &lossy, 256);\n+    assert!(asymmetric.completion_time < naive.completion_time);\n+}\n+\n+#[test]\n+fn send_window_of_one_completes_without_panicking() {\n+    let config = TransportConfig {\n+        send_window_packets: 1,\n+        ..TransportConfig::default()\n+    };\n+    let bottleneck = scenario(\"reverse_path_bottleneck\");\n+    assert!(run_asymmetric_transport(&config, &bottleneck, 16).completed);\n+}\n+\n+#[test]\n+fn ack_rate_limit_of_zero_does_not_panic_and_still_acknowledges() {\n+    let mut state = AckState::new(0x161, 64, 32, 0);\n+    assert_eq!(state.record(0), RecordOutcome::New);\n+    let ack = state\n+        .emit_if_due(Duration::ZERO, Duration::ZERO)\n+        .expect(\"an unthrottled receiver still emits acknowledgements\");\n+    assert!(ack.ranges.iter().any(|range| range.contains(0)));\n+}\ndiff --git a/Poc/22-asymmetric-transport/tests/receiver_state.rs b/Poc/22-asymmetric-transport/tests/receiver_state.rs\nnew file mode 100644\nindex 0000000..a344e0f\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/receiver_state.rs\n@@ -0,0 +1,13 @@\n+//! Receiver memory bounds: a far-ahead (forged) sequence must not lock out the receive window.\n+\n+use asymmetric_transport::{AckState, RecordOutcome};\n+\n+#[test]\n+fn far_ahead_sequence_does_not_lock_out_the_session() {\n+    let mut state = AckState::new(1, 64, 32, 20);\n+    for sequence in 0..10 {\n+        state.record(sequence);\n+    }\n+    state.record(u64::MAX);\n+    assert_eq!(state.record(10), RecordOutcome::New);\n+}\ndiff --git a/Poc/22-asymmetric-transport/tests/review.rs b/Poc/22-asymmetric-transport/tests/review.rs\ndeleted file mode 100644\nindex 009aaa2..0000000\n--- a/Poc/22-asymmetric-transport/tests/review.rs\n+++ /dev/null\n@@ -1,223 +0,0 @@\n-use asymmetric_transport::{\n-    AckFrame, AckRange, AckState, Frame, JitterQueue, RecordOutcome, Scenario, SenderAckState,\n-    SessionSecurity, TransportConfig, compare_timing_linkability, required_scenarios,\n-    run_asymmetric_transport, run_naive_baseline, run_udp_loopback,\n-};\n-use std::time::Duration;\n-\n-fn scenario(name: &str) -> Scenario {\n-    required_scenarios()\n-        .into_iter()\n-        .find(|candidate| candidate.name == name)\n-        .unwrap()\n-}\n-\n-#[test]\n-fn loopback_past_one_receive_window_completes() {\n-    let metrics = run_udp_loopback(&TransportConfig::default(), 65).unwrap();\n-    assert_eq!(metrics.packets_received, 65);\n-    assert!(metrics.completed);\n-}\n-\n-#[test]\n-fn jitter_without_loss_causes_no_retransmissions() {\n-    let mut jittered = scenario(\"high_seeded_jitter\");\n-    jittered.data_loss_percent = 0;\n-    jittered.ack_loss_percent = 0;\n-    jittered.reorder = false;\n-    jittered.duplicate_acks = false;\n-    let metrics = run_asymmetric_transport(&TransportConfig::default(), &jittered, 256);\n-    assert_eq!(metrics.retransmissions, 0);\n-}\n-\n-#[test]\n-fn asymmetric_sender_beats_baseline_with_rto_above_rtt() {\n-    // random_loss has a 195 ms RTT, an adaptive RTO would settle above it\n-    let baseline = TransportConfig {\n-        naive_retransmit_timeout: Duration::from_secs(1),\n-        ..TransportConfig::default()\n-    };\n-    let lossy = scenario(\"random_loss\");\n-    let naive = run_naive_baseline(&baseline, &lossy, 256);\n-    let asymmetric = run_asymmetric_transport(&TransportConfig::default(), &lossy, 256);\n-    assert!(asymmetric.completion_time < naive.completion_time);\n-}\n-\n-#[test]\n-fn far_ahead_sequence_does_not_lock_out_the_session() {\n-    let mut state = AckState::new(1, 64, 32, 20);\n-    for sequence in 0..10 {\n-        state.record(sequence);\n-    }\n-    state.record(u64::MAX);\n-    assert_eq!(state.record(10), RecordOutcome::New);\n-}\n-\n-#[test]\n-fn real_jitter_queue_output_lowers_linkability_for_every_seed() {\n-    let source_ms: [u64; 8] = [0, 10, 35, 50, 90, 105, 160, 180];\n-    for seed in 0..4 {\n-        let queue = JitterQueue::<u64>::new(seed, Duration::from_millis(80), 64);\n-        let mut shaped_ms: Vec<u64> = source_ms\n-            .iter()\n-            .zip(0..)\n-            .map(|(sent_ms, sequence)| {\n-                let jitter = queue.delay_for(sequence);\n-                sent_ms + u64::try_from(jitter.as_millis()).unwrap()\n-            })\n-            .collect();\n-        shaped_ms.sort_unstable();\n-        let scores = compare_timing_linkability(&source_ms, &source_ms, &shaped_ms);\n-        assert!(\n-            scores.shaped_score < 0.9,\n-            \"seed {seed} shaped score {:.3}\",\n-            scores.shaped_score\n-        );\n-    }\n-}\n-\n-#[test]\n-fn send_window_of_one_completes_without_panicking() {\n-    let config = TransportConfig {\n-        send_window_packets: 1,\n-        ..TransportConfig::default()\n-    };\n-    let bottleneck = scenario(\"reverse_path_bottleneck\");\n-    assert!(run_asymmetric_transport(&config, &bottleneck, 16).completed);\n-}\n-\n-#[test]\n-fn loopback_zero_loss_and_injected_loss_runs() {\n-    // Zero-loss run: the measured timeout exceeds the measured RTT, so no spurious retransmissions.\n-    let lossless = run_udp_loopback(&TransportConfig::default(), 128).unwrap();\n-    println!(\n-        \"loopback zero-loss n=128: completed={} received={} retransmissions={} acks={} cumulative_acks={} decoys={} measured_rtt={:?} rto={:?} cwnd={} streams={}\",\n-        lossless.completed,\n-        lossless.packets_received,\n-        lossless.retransmissions,\n-        lossless.ack_datagrams,\n-        lossless.cumulative_ack_datagrams,\n-        lossless.decoy_datagrams,\n-        lossless.measured_rtt,\n-        lossless.retransmission_timeout,\n-        lossless.congestion_window_packets,\n-        lossless.stream_count,\n-    );\n-    assert!(lossless.completed);\n-    assert_eq!(lossless.packets_received, 128);\n-    assert_eq!(\n-        lossless.retransmissions, 0,\n-        \"zero-loss loopback retransmitted {} times\",\n-        lossless.retransmissions\n-    );\n-    assert!(lossless.measured_rtt > Duration::ZERO);\n-    assert!(lossless.retransmission_timeout >= lossless.measured_rtt);\n-\n-    // Injected-loss run: the same path with deterministic loss forces real retransmissions and\n-    // still delivers every packet.\n-    let lossy = run_udp_loopback(\n-        &TransportConfig {\n-            udp_loss_percent: 25,\n-            ..TransportConfig::default()\n-        },\n-        128,\n-    )\n-    .unwrap();\n-    println!(\n-        \"loopback injected-loss p=25 n=128: completed={} received={} retransmissions={} acks={} cumulative_acks={} decoys={} measured_rtt={:?} rto={:?} cwnd={}\",\n-        lossy.completed,\n-        lossy.packets_received,\n-        lossy.retransmissions,\n-        lossy.ack_datagrams,\n-        lossy.cumulative_ack_datagrams,\n-        lossy.decoy_datagrams,\n-        lossy.measured_rtt,\n-        lossy.retransmission_timeout,\n-        lossy.congestion_window_packets,\n-    );\n-    assert!(lossy.completed);\n-    assert_eq!(lossy.packets_received, 128);\n-    assert!(\n-        lossy.retransmissions > 0,\n-        \"injected-loss loopback produced no retransmissions\"\n-    );\n-}\n-\n-#[test]\n-fn loopback_transfers_beyond_128_packets() {\n-    // A transfer well beyond the 128-packet default window, with loss, still completes and every\n-    // distinct packet is delivered across the multiplexed streams.\n-    let metrics = run_udp_loopback(\n-        &TransportConfig {\n-            udp_loss_percent: 10,\n-            ..TransportConfig::default()\n-        },\n-        300,\n-    )\n-    .unwrap();\n-    println!(\n-        \"loopback beyond-128 p=10 n=300: completed={} received={} sent={} retransmissions={} acks={} measured_rtt={:?} rto={:?} streams={}\",\n-        metrics.completed,\n-        metrics.packets_received,\n-        metrics.packets_sent,\n-        metrics.retransmissions,\n-        metrics.ack_datagrams,\n-        metrics.measured_rtt,\n-        metrics.retransmission_timeout,\n-        metrics.stream_count,\n-    );\n-    assert!(metrics.completed);\n-    assert_eq!(metrics.packets_received, 300);\n-    assert!(metrics.packets_sent > 128);\n-    assert!(metrics.stream_count >= 2);\n-}\n-\n-#[test]\n-fn ack_rate_limit_of_zero_does_not_panic_and_still_acknowledges() {\n-    let mut state = AckState::new(0x161, 64, 32, 0);\n-    assert_eq!(state.record(0), RecordOutcome::New);\n-    let ack = state\n-        .emit_if_due(Duration::ZERO, Duration::ZERO)\n-        .expect(\"an unthrottled receiver still emits acknowledgements\");\n-    assert!(ack.ranges.iter().any(|range| range.contains(0)));\n-}\n-\n-#[test]\n-fn forged_frames_and_acknowledgements_are_rejected() {\n-    let key = 0x0bad_c0de_1611_5eed;\n-    let security = SessionSecurity::new(key);\n-\n-    // Forward-path forgery: a matching session id with no authenticator is rejected.\n-    let forged_data = Frame::Ack(AckFrame {\n-        session_id: 0x161,\n-        stream_id: 0x1611,\n-        receiver_delay_ms: 0,\n-        tag: 0,\n-        ranges: vec![AckRange::new(0, 1).unwrap()],\n-    });\n-    assert!(!security.verify_return(&forged_data));\n-\n-    // A sender that only trusts authenticated ACKs never marks in-flight data delivered.\n-    let mut sender = SenderAckState::default();\n-    sender.record_sent(0);\n-    sender.record_sent(1);\n-    if security.verify_return(&forged_data)\n-        && let Frame::Ack(ack) = &forged_data\n-    {\n-        sender.apply(ack, 1024);\n-    }\n-    assert_eq!(\n-        sender.acknowledged.len(),\n-        0,\n-        \"a forged ACK must not acknowledge in-flight data\"\n-    );\n-\n-    // The same frame signed with the key is accepted and acknowledges the sent data.\n-    let mut signed = forged_data;\n-    security.sign_return(&mut signed);\n-    assert!(security.verify_return(&signed));\n-    if let Frame::Ack(ack) = &signed {\n-        assert_eq!(sender.apply(ack, 1024), 2);\n-    }\n-    assert_eq!(sender.acknowledged.len(), 2);\n-}\ndiff --git a/Poc/22-asymmetric-transport/tests/session_security.rs b/Poc/22-asymmetric-transport/tests/session_security.rs\nnew file mode 100644\nindex 0000000..bf0e7c3\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/session_security.rs\n@@ -0,0 +1,44 @@\n+//! Session security: forged frames without a valid authenticator are rejected and never advance\n+//! sender acknowledgement state; the same frame signed with the session key is accepted.\n+\n+use asymmetric_transport::{AckFrame, AckRange, Frame, SenderAckState, SessionSecurity};\n+\n+#[test]\n+fn forged_frames_and_acknowledgements_are_rejected() {\n+    let key = 0x0bad_c0de_1611_5eed;\n+    let security = SessionSecurity::new(key);\n+\n+    // Forward-path forgery: a matching session id with no authenticator is rejected.\n+    let forged_data = Frame::Ack(AckFrame {\n+        session_id: 0x161,\n+        stream_id: 0x1611,\n+        receiver_delay_ms: 0,\n+        tag: 0,\n+        ranges: vec![AckRange::new(0, 1).unwrap()],\n+    });\n+    assert!(!security.verify_return(&forged_data));\n+\n+    // A sender that only trusts authenticated ACKs never marks in-flight data delivered.\n+    let mut sender = SenderAckState::default();\n+    sender.record_sent(0);\n+    sender.record_sent(1);\n+    if security.verify_return(&forged_data)\n+        && let Frame::Ack(ack) = &forged_data\n+    {\n+        sender.apply(ack, 1024);\n+    }\n+    assert_eq!(\n+        sender.acknowledged.len(),\n+        0,\n+        \"a forged ACK must not acknowledge in-flight data\"\n+    );\n+\n+    // The same frame signed with the key is accepted and acknowledges the sent data.\n+    let mut signed = forged_data;\n+    security.sign_return(&mut signed);\n+    assert!(security.verify_return(&signed));\n+    if let Frame::Ack(ack) = &signed {\n+        assert_eq!(sender.apply(ack, 1024), 2);\n+    }\n+    assert_eq!(sender.acknowledged.len(), 2);\n+}\n-- \n2.43.0\n\n","patch_unified_diff":"diff --git a/Poc/22-asymmetric-transport/tests/linkability.rs b/Poc/22-asymmetric-transport/tests/linkability.rs\nnew file mode 100644\nindex 0000000..b51ef94\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/linkability.rs\n@@ -0,0 +1,28 @@\n+//! Timing-linkability: the real jitter queue must lower the sample gap-correlation score for\n+//! every seed, not just some.\n+\n+use asymmetric_transport::{JitterQueue, compare_timing_linkability};\n+use std::time::Duration;\n+\n+#[test]\n+fn real_jitter_queue_output_lowers_linkability_for_every_seed() {\n+    let source_ms: [u64; 8] = [0, 10, 35, 50, 90, 105, 160, 180];\n+    for seed in 0..4 {\n+        let queue = JitterQueue::<u64>::new(seed, Duration::from_millis(80), 64);\n+        let mut shaped_ms: Vec<u64> = source_ms\n+            .iter()\n+            .zip(0..)\n+            .map(|(sent_ms, sequence)| {\n+                let jitter = queue.delay_for(sequence);\n+                sent_ms + u64::try_from(jitter.as_millis()).unwrap()\n+            })\n+            .collect();\n+        shaped_ms.sort_unstable();\n+        let scores = compare_timing_linkability(&source_ms, &source_ms, &shaped_ms);\n+        assert!(\n+            scores.shaped_score < 0.9,\n+            \"seed {seed} shaped score {:.3}\",\n+            scores.shaped_score\n+        );\n+    }\n+}\ndiff --git a/Poc/22-asymmetric-transport/tests/loopback.rs b/Poc/22-asymmetric-transport/tests/loopback.rs\nnew file mode 100644\nindex 0000000..c591bbe\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/loopback.rs\n@@ -0,0 +1,98 @@\n+//! Loopback UDP demonstrations over real sockets: a transfer past one receive window, zero-loss\n+//! and injected-loss runs, and transfers beyond the default window.\n+\n+use asymmetric_transport::{TransportConfig, run_udp_loopback};\n+use std::time::Duration;\n+\n+#[test]\n+fn loopback_past_one_receive_window_completes() {\n+    let metrics = run_udp_loopback(&TransportConfig::default(), 65).unwrap();\n+    assert_eq!(metrics.packets_received, 65);\n+    assert!(metrics.completed);\n+}\n+\n+#[test]\n+fn loopback_zero_loss_and_injected_loss_runs() {\n+    // Zero-loss run: the measured timeout exceeds the measured RTT, so no spurious retransmissions.\n+    let lossless = run_udp_loopback(&TransportConfig::default(), 128).unwrap();\n+    println!(\n+        \"loopback zero-loss n=128: completed={} received={} retransmissions={} acks={} cumulative_acks={} decoys={} measured_rtt={:?} rto={:?} cwnd={} streams={}\",\n+        lossless.completed,\n+        lossless.packets_received,\n+        lossless.retransmissions,\n+        lossless.ack_datagrams,\n+        lossless.cumulative_ack_datagrams,\n+        lossless.decoy_datagrams,\n+        lossless.measured_rtt,\n+        lossless.retransmission_timeout,\n+        lossless.congestion_window_packets,\n+        lossless.stream_count,\n+    );\n+    assert!(lossless.completed);\n+    assert_eq!(lossless.packets_received, 128);\n+    assert_eq!(\n+        lossless.retransmissions, 0,\n+        \"zero-loss loopback retransmitted {} times\",\n+        lossless.retransmissions\n+    );\n+    assert!(lossless.measured_rtt > Duration::ZERO);\n+    assert!(lossless.retransmission_timeout >= lossless.measured_rtt);\n+\n+    // Injected-loss run: the same path with deterministic loss forces real retransmissions and\n+    // still delivers every packet.\n+    let lossy = run_udp_loopback(\n+        &TransportConfig {\n+            udp_loss_percent: 25,\n+            ..TransportConfig::default()\n+        },\n+        128,\n+    )\n+    .unwrap();\n+    println!(\n+        \"loopback injected-loss p=25 n=128: completed={} received={} retransmissions={} acks={} cumulative_acks={} decoys={} measured_rtt={:?} rto={:?} cwnd={}\",\n+        lossy.completed,\n+        lossy.packets_received,\n+        lossy.retransmissions,\n+        lossy.ack_datagrams,\n+        lossy.cumulative_ack_datagrams,\n+        lossy.decoy_datagrams,\n+        lossy.measured_rtt,\n+        lossy.retransmission_timeout,\n+        lossy.congestion_window_packets,\n+    );\n+    assert!(lossy.completed);\n+    assert_eq!(lossy.packets_received, 128);\n+    assert!(\n+        lossy.retransmissions > 0,\n+        \"injected-loss loopback produced no retransmissions\"\n+    );\n+}\n+\n+#[test]\n+fn loopback_transfers_beyond_128_packets() {\n+    // A transfer well beyond the 128-packet default window, with loss, still completes and every\n+    // distinct packet is delivered across the multiplexed streams.\n+    let metrics = run_udp_loopback(\n+        &TransportConfig {\n+            udp_loss_percent: 10,\n+            ..TransportConfig::default()\n+        },\n+        300,\n+    )\n+    .unwrap();\n+    println!(\n+        \"loopback beyond-128 p=10 n=300: completed={} received={} sent={} retransmissions={} acks={} measured_rtt={:?} rto={:?} streams={}\",\n+        metrics.completed,\n+        metrics.packets_received,\n+        metrics.packets_sent,\n+        metrics.retransmissions,\n+        metrics.ack_datagrams,\n+        metrics.measured_rtt,\n+        metrics.retransmission_timeout,\n+        metrics.stream_count,\n+    );\n+    assert!(metrics.completed);\n+    assert_eq!(metrics.packets_received, 300);\n+    assert!(metrics.packets_sent > 128);\n+    assert!(metrics.stream_count >= 2);\n+}\ndiff --git a/Poc/22-asymmetric-transport/tests/loss_recovery.rs b/Poc/22-asymmetric-transport/tests/loss_recovery.rs\nnew file mode 100644\nindex 0000000..ed281f7\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/loss_recovery.rs\n@@ -0,0 +1,60 @@\n+//! Sender loss-recovery behaviour: jitter without loss must not retransmit, the asymmetric\n+//! sender must beat a naive RTO baseline whose timeout sits above the RTT, a send window of one\n+//! must complete, and a zero ACK rate limit must not panic.\n+\n+use asymmetric_transport::{\n+    AckState, RecordOutcome, Scenario, TransportConfig, required_scenarios,\n+    run_asymmetric_transport, run_naive_baseline,\n+};\n+use std::time::Duration;\n+\n+fn scenario(name: &str) -> Scenario {\n+    required_scenarios()\n+        .into_iter()\n+        .find(|candidate| candidate.name == name)\n+        .unwrap()\n+}\n+\n+#[test]\n+fn jitter_without_loss_causes_no_retransmissions() {\n+    let mut jittered = scenario(\"high_seeded_jitter\");\n+    jittered.data_loss_percent = 0;\n+    jittered.ack_loss_percent = 0;\n+    jittered.reorder = false;\n+    jittered.duplicate_acks = false;\n+    let metrics = run_asymmetric_transport(&TransportConfig::default(), &jittered, 256);\n+    assert_eq!(metrics.retransmissions, 0);\n+}\n+\n+#[test]\n+fn asymmetric_sender_beats_baseline_with_rto_above_rtt() {\n+    // random_loss has a 195 ms RTT, an adaptive RTO would settle above it\n+    let baseline = TransportConfig {\n+        naive_retransmit_timeout: Duration::from_secs(1),\n+        ..TransportConfig::default()\n+    };\n+    let lossy = scenario(\"random_loss\");\n+    let naive = run_naive_baseline(&baseline, &lossy, 256);\n+    let asymmetric = run_asymmetric_transport(&TransportConfig::default(), &lossy, 256);\n+    assert!(asymmetric.completion_time < naive.completion_time);\n+}\n+\n+#[test]\n+fn send_window_of_one_completes_without_panicking() {\n+    let config = TransportConfig {\n+        send_window_packets: 1,\n+        ..TransportConfig::default()\n+    };\n+    let bottleneck = scenario(\"reverse_path_bottleneck\");\n+    assert!(run_asymmetric_transport(&config, &bottleneck, 16).completed);\n+}\n+\n+#[test]\n+fn ack_rate_limit_of_zero_does_not_panic_and_still_acknowledges() {\n+    let mut state = AckState::new(0x161, 64, 32, 0);\n+    assert_eq!(state.record(0), RecordOutcome::New);\n+    let ack = state\n+        .emit_if_due(Duration::ZERO, Duration::ZERO)\n+        .expect(\"an unthrottled receiver still emits acknowledgements\");\n+    assert!(ack.ranges.iter().any(|range| range.contains(0)));\n+}\ndiff --git a/Poc/22-asymmetric-transport/tests/receiver_state.rs b/Poc/22-asymmetric-transport/tests/receiver_state.rs\nnew file mode 100644\nindex 0000000..a344e0f\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/receiver_state.rs\n@@ -0,0 +1,13 @@\n+//! Receiver memory bounds: a far-ahead (forged) sequence must not lock out the receive window.\n+\n+use asymmetric_transport::{AckState, RecordOutcome};\n+\n+#[test]\n+fn far_ahead_sequence_does_not_lock_out_the_session() {\n+    let mut state = AckState::new(1, 64, 32, 20);\n+    for sequence in 0..10 {\n+        state.record(sequence);\n+    }\n+    state.record(u64::MAX);\n+    assert_eq!(state.record(10), RecordOutcome::New);\n+}\ndiff --git a/Poc/22-asymmetric-transport/tests/review.rs b/Poc/22-asymmetric-transport/tests/review.rs\ndeleted file mode 100644\nindex 009aaa2..0000000\n--- a/Poc/22-asymmetric-transport/tests/review.rs\n+++ /dev/null\n@@ -1,223 +0,0 @@\n-use asymmetric_transport::{\n-    AckFrame, AckRange, AckState, Frame, JitterQueue, RecordOutcome, Scenario, SenderAckState,\n-    SessionSecurity, TransportConfig, compare_timing_linkability, required_scenarios,\n-    run_asymmetric_transport, run_naive_baseline, run_udp_loopback,\n-};\n-use std::time::Duration;\n-\n-fn scenario(name: &str) -> Scenario {\n-    required_scenarios()\n-        .into_iter()\n-        .find(|candidate| candidate.name == name)\n-        .unwrap()\n-}\n-\n-#[test]\n-fn loopback_past_one_receive_window_completes() {\n-    let metrics = run_udp_loopback(&TransportConfig::default(), 65).unwrap();\n-    assert_eq!(metrics.packets_received, 65);\n-    assert!(metrics.completed);\n-}\n-\n-#[test]\n-fn jitter_without_loss_causes_no_retransmissions() {\n-    let mut jittered = scenario(\"high_seeded_jitter\");\n-    jittered.data_loss_percent = 0;\n-    jittered.ack_loss_percent = 0;\n-    jittered.reorder = false;\n-    jittered.duplicate_acks = false;\n-    let metrics = run_asymmetric_transport(&TransportConfig::default(), &jittered, 256);\n-    assert_eq!(metrics.retransmissions, 0);\n-}\n-\n-#[test]\n-fn asymmetric_sender_beats_baseline_with_rto_above_rtt() {\n-    // random_loss has a 195 ms RTT, an adaptive RTO would settle above it\n-    let baseline = TransportConfig {\n-        naive_retransmit_timeout: Duration::from_secs(1),\n-        ..TransportConfig::default()\n-    };\n-    let lossy = scenario(\"random_loss\");\n-    let naive = run_naive_baseline(&baseline, &lossy, 256);\n-    let asymmetric = run_asymmetric_transport(&TransportConfig::default(), &lossy, 256);\n-    assert!(asymmetric.completion_time < naive.completion_time);\n-}\n-\n-#[test]\n-fn far_ahead_sequence_does_not_lock_out_the_session() {\n-    let mut state = AckState::new(1, 64, 32, 20);\n-    for sequence in 0..10 {\n-        state.record(sequence);\n-    }\n-    state.record(u64::MAX);\n-    assert_eq!(state.record(10), RecordOutcome::New);\n-}\n-\n-#[test]\n-fn real_jitter_queue_output_lowers_linkability_for_every_seed() {\n-    let source_ms: [u64; 8] = [0, 10, 35, 50, 90, 105, 160, 180];\n-    for seed in 0..4 {\n-        let queue = JitterQueue::<u64>::new(seed, Duration::from_millis(80), 64);\n-        let mut shaped_ms: Vec<u64> = source_ms\n-            .iter()\n-            .zip(0..)\n-            .map(|(sent_ms, sequence)| {\n-                let jitter = queue.delay_for(sequence);\n-                sent_ms + u64::try_from(jitter.as_millis()).unwrap()\n-            })\n-            .collect();\n-        shaped_ms.sort_unstable();\n-        let scores = compare_timing_linkability(&source_ms, &source_ms, &shaped_ms);\n-        assert!(\n-            scores.shaped_score < 0.9,\n-            \"seed {seed} shaped score {:.3}\",\n-            scores.shaped_score\n-        );\n-    }\n-}\n-\n-#[test]\n-fn send_window_of_one_completes_without_panicking() {\n-    let config = TransportConfig {\n-        send_window_packets: 1,\n-        ..TransportConfig::default()\n-    };\n-    let bottleneck = scenario(\"reverse_path_bottleneck\");\n-    assert!(run_asymmetric_transport(&config, &bottleneck, 16).completed);\n-}\n-\n-#[test]\n-fn loopback_zero_loss_and_injected_loss_runs() {\n-    // Zero-loss run: the measured timeout exceeds the measured RTT, so no spurious retransmissions.\n-    let lossless = run_udp_loopback(&TransportConfig::default(), 128).unwrap();\n-    println!(\n-        \"loopback zero-loss n=128: completed={} received={} retransmissions={} acks={} cumulative_acks={} decoys={} measured_rtt={:?} rto={:?} cwnd={} streams={}\",\n-        lossless.completed,\n-        lossless.packets_received,\n-        lossless.retransmissions,\n-        lossless.ack_datagrams,\n-        lossless.cumulative_ack_datagrams,\n-        lossless.decoy_datagrams,\n-        lossless.measured_rtt,\n-        lossless.retransmission_timeout,\n-        lossless.congestion_window_packets,\n-        lossless.stream_count,\n-    );\n-    assert!(lossless.completed);\n-    assert_eq!(lossless.packets_received, 128);\n-    assert_eq!(\n-        lossless.retransmissions, 0,\n-        \"zero-loss loopback retransmitted {} times\",\n-        lossless.retransmissions\n-    );\n-    assert!(lossless.measured_rtt > Duration::ZERO);\n-    assert!(lossless.retransmission_timeout >= lossless.measured_rtt);\n-\n-    // Injected-loss run: the same path with deterministic loss forces real retransmissions and\n-    // still delivers every packet.\n-    let lossy = run_udp_loopback(\n-        &TransportConfig {\n-            udp_loss_percent: 25,\n-            ..TransportConfig::default()\n-        },\n-        128,\n-    )\n-    .unwrap();\n-    println!(\n-        \"loopback injected-loss p=25 n=128: completed={} received={} retransmissions={} acks={} cumulative_acks={} decoys={} measured_rtt={:?} rto={:?} cwnd={}\",\n-        lossy.completed,\n-        lossy.packets_received,\n-        lossy.retransmissions,\n-        lossy.ack_datagrams,\n-        lossy.cumulative_ack_datagrams,\n-        lossy.decoy_datagrams,\n-        lossy.measured_rtt,\n-        lossy.retransmission_timeout,\n-        lossy.congestion_window_packets,\n-    );\n-    assert!(lossy.completed);\n-    assert_eq!(lossy.packets_received, 128);\n-    assert!(\n-        lossy.retransmissions > 0,\n-        \"injected-loss loopback produced no retransmissions\"\n-    );\n-}\n-\n-#[test]\n-fn loopback_transfers_beyond_128_packets() {\n-    // A transfer well beyond the 128-packet default window, with loss, still completes and every\n-    // distinct packet is delivered across the multiplexed streams.\n-    let metrics = run_udp_loopback(\n-        &TransportConfig {\n-            udp_loss_percent: 10,\n-            ..TransportConfig::default()\n-        },\n-        300,\n-    )\n-    .unwrap();\n-    println!(\n-        \"loopback beyond-128 p=10 n=300: completed={} received={} sent={} retransmissions={} acks={} measured_rtt={:?} rto={:?} streams={}\",\n-        metrics.completed,\n-        metrics.packets_received,\n-        metrics.packets_sent,\n-        metrics.retransmissions,\n-        metrics.ack_datagrams,\n-        metrics.measured_rtt,\n-        metrics.retransmission_timeout,\n-        metrics.stream_count,\n-    );\n-    assert!(metrics.completed);\n-    assert_eq!(metrics.packets_received, 300);\n-    assert!(metrics.packets_sent > 128);\n-    assert!(metrics.stream_count >= 2);\n-}\n-\n-#[test]\n-fn ack_rate_limit_of_zero_does_not_panic_and_still_acknowledges() {\n-    let mut state = AckState::new(0x161, 64, 32, 0);\n-    assert_eq!(state.record(0), RecordOutcome::New);\n-    let ack = state\n-        .emit_if_due(Duration::ZERO, Duration::ZERO)\n-        .expect(\"an unthrottled receiver still emits acknowledgements\");\n-    assert!(ack.ranges.iter().any(|range| range.contains(0)));\n-}\n-\n-#[test]\n-fn forged_frames_and_acknowledgements_are_rejected() {\n-    let key = 0x0bad_c0de_1611_5eed;\n-    let security = SessionSecurity::new(key);\n-\n-    // Forward-path forgery: a matching session id with no authenticator is rejected.\n-    let forged_data = Frame::Ack(AckFrame {\n-        session_id: 0x161,\n-        stream_id: 0x1611,\n-        receiver_delay_ms: 0,\n-        tag: 0,\n-        ranges: vec![AckRange::new(0, 1).unwrap()],\n-    });\n-    assert!(!security.verify_return(&forged_data));\n-\n-    // A sender that only trusts authenticated ACKs never marks in-flight data delivered.\n-    let mut sender = SenderAckState::default();\n-    sender.record_sent(0);\n-    sender.record_sent(1);\n-    if security.verify_return(&forged_data)\n-        && let Frame::Ack(ack) = &forged_data\n-    {\n-        sender.apply(ack, 1024);\n-    }\n-    assert_eq!(\n-        sender.acknowledged.len(),\n-        0,\n-        \"a forged ACK must not acknowledge in-flight data\"\n-    );\n-\n-    // The same frame signed with the key is accepted and acknowledges the sent data.\n-    let mut signed = forged_data;\n-    security.sign_return(&mut signed);\n-    assert!(security.verify_return(&signed));\n-    if let Frame::Ack(ack) = &signed {\n-        assert_eq!(sender.apply(ack, 1024), 2);\n-    }\n-    assert_eq!(sender.acknowledged.len(), 2);\n-}\ndiff --git a/Poc/22-asymmetric-transport/tests/session_security.rs b/Poc/22-asymmetric-transport/tests/session_security.rs\nnew file mode 100644\nindex 0000000..bf0e7c3\n--- /dev/null\n+++ b/Poc/22-asymmetric-transport/tests/session_security.rs\n@@ -0,0 +1,44 @@\n+//! Session security: forged frames without a valid authenticator are rejected and never advance\n+//! sender acknowledgement state; the same frame signed with the session key is accepted.\n+\n+use asymmetric_transport::{AckFrame, AckRange, Frame, SenderAckState, SessionSecurity};\n+\n+#[test]\n+fn forged_frames_and_acknowledgements_are_rejected() {\n+    let key = 0x0bad_c0de_1611_5eed;\n+    let security = SessionSecurity::new(key);\n+\n+    // Forward-path forgery: a matching session id with no authenticator is rejected.\n+    let forged_data = Frame::Ack(AckFrame {\n+        session_id: 0x161,\n+        stream_id: 0x1611,\n+        receiver_delay_ms: 0,\n+        tag: 0,\n+        ranges: vec![AckRange::new(0, 1).unwrap()],\n+    });\n+    assert!(!security.verify_return(&forged_data));\n+\n+    // A sender that only trusts authenticated ACKs never marks in-flight data delivered.\n+    let mut sender = SenderAckState::default();\n+    sender.record_sent(0);\n+    sender.record_sent(1);\n+    if security.verify_return(&forged_data)\n+        && let Frame::Ack(ack) = &forged_data\n+    {\n+        sender.apply(ack, 1024);\n+    }\n+    assert_eq!(\n+        sender.acknowledged.len(),\n+        0,\n+        \"a forged ACK must not acknowledge in-flight data\"\n+    );\n+\n+    // The same frame signed with the key is accepted and acknowledges the sent data.\n+    let mut signed = forged_data;\n+    security.sign_return(&mut signed);\n+    assert!(security.verify_return(&signed));\n+    if let Frame::Ack(ack) = &signed {\n+        assert_eq!(sender.apply(ack, 1024), 2);\n+    }\n+    assert_eq!(sender.acknowledged.len(), 2);\n+}\n","lint_output":{"cargo_fmt_all_check":"FMT_EXIT=0 (clean)","cargo_clippy_all_targets_-D_warnings":"CLIPPY_EXIT=0 (clean)","raw":"FMT_EXIT=0\n    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s\nCLIPPY_EXIT=0"},"test_output":{"cargo_test_all_targets":"Running unittests src/lib.rs (target/debug/deps/asymmetric_transport-dc0324340cc0a6e9)\ntest result: ok. 35 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 16.61s\n     Running unittests src/main.rs (target/debug/deps/asymmetric_transport-6e44dea6dea6ce68)\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n     Running tests/demonstrates.rs (target/debug/deps/demonstrates-dcbf710e479874b5)\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.91s\n     Running tests/linkability.rs (target/debug/deps/linkability-f24c4df37b806357)\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n     Running tests/loopback.rs (target/debug/deps/loopback-f765b8d6707c34ce)\ntest result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.84s\n     Running tests/loss_recovery.rs (target/debug/deps/loss_recovery-b26842bac8a4549e)\ntest result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n     Running tests/receiver_state.rs (target/debug/deps/receiver_state-3e8715938be4dd77)\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n     Running tests/session_security.rs (target/debug/deps/session_security-d2f4380adea0af79)\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\n     Running tests/threat_model.rs (target/debug/deps/threat_model-4842b41c8b8d5894)\ntest result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s","review_rs_removed_proof":"tests/review.rs removed\ndemonstrates.rs\nlinkability.rs\nloopback.rs\nloss_recovery.rs\nreceiver_state.rs\nsession_security.rs\nthreat_model.rs","moved_test_files":"tests/linkability.rs\ntests/loss_recovery.rs","summary":"cargo fmt --all --check and cargo clippy --all-targets -- -D warnings both exit 0. cargo test --all-targets all green: lib unit tests (35), tests/demonstrates.rs (1), tests/linkability.rs (1), tests/loopback.rs (3), tests/loss_recovery.rs (4), tests/receiver_state.rs (1), tests/session_security.rs (1), tests/threat_model.rs (8); 0 failed. tests/review.rs no longer exists."},"fix_summary":{"rand0_item":"13770: 'tests/review.rs was only there to show the bugs. Don't keep it as part of the PoC: fix the bugs and cover them with tests in your own files. Move the 4 tests you added to it as well.'","what_changed":"tests/review.rs is deleted entirely. Every test it carried is moved verbatim into a focused integration-test file named for the behaviour it covers; no single catch-all 'review' file remains and no test is left in tests/review.rs.","the_4_tests_i_added":{"jitter_without_loss_causes_no_retransmissions":"tests/loss_recovery.rs","asymmetric_sender_beats_baseline_with_rto_above_rtt":"tests/loss_recovery.rs","real_jitter_queue_output_lowers_linkability_for_every_seed":"tests/linkability.rs","send_window_of_one_completes_without_panicking":"tests/loss_recovery.rs"},"placement":{"tests/loopback.rs":"loopback_past_one_receive_window_completes, loopback_zero_loss_and_injected_loss_runs, loopback_transfers_beyond_128_packets","tests/loss_recovery.rs":"jitter_without_loss_causes_no_retransmissions, asymmetric_sender_beats_baseline_with_rto_above_rtt, send_window_of_one_completes_without_panicking, ack_rate_limit_of_zero_does_not_panic_and_still_acknowledges","tests/linkability.rs":"real_jitter_queue_output_lowers_linkability_for_every_seed","tests/receiver_state.rs":"far_ahead_sequence_does_not_lock_out_the_session","tests/session_security.rs":"forged_frames_and_acknowledgements_are_rejected"},"bugs_covered":"The moved tests exercise the fixed behaviour against the live code (the bug fixes landed on the integrated PR head): no retransmissions for jitter without loss; the asymmetric sender beats a 1 s-RTO naive baseline whose timeout sits above the ~195 ms RTT; the real jitter queue lowers the sample timing-linkability score for every seed; send_window_packets=1 completes without a QueueFull panic; a far-ahead forged sequence does not lock out the window; a loopback transfer past one receive window completes.","no_hard_coded_values":"Test bodies are moved verbatim; each asserts against the real API. No pass output is hard-coded, no test lives in tests/review.rs, no unrelated refactor."},"notes":"Fix for rand0 PR #187 comment 13770. Real transport code only, no simulator-only code, no hard-coded test answers, no unrelated refactor, no maintainer contact, no secrets, no wallet or pricing changes. cargo fmt --check clean, clippy --all-targets -D warnings clean, cargo test --all-targets all green; tests/review.rs removed."},"attachments":[],"redactions":0,"note":"Shown as stored."}