Skip to content

feat(hotas): enhance VKB and Virpil prosumer protocol support#70

Open
EffortlessSteven wants to merge 3 commits intomainfrom
feat/prosumer-protocols
Open

feat(hotas): enhance VKB and Virpil prosumer protocol support#70
EffortlessSteven wants to merge 3 commits intomainfrom
feat/prosumer-protocols

Conversation

@EffortlessSteven
Copy link
Member

Summary

Enhances VKB and Virpil HOTAS crates with additional protocol support, device profiles, and utilities.

VKB Crate (flight-hotas-vkb)

  • T-Rudder parser (\ _rudder.rs): New HID report parser for VKB T-Rudder Mk.IV/V pedals — 3 axes (left toe brake, right toe brake, rudder), hall-effect sensors, with report ID stripping support
  • Axis calibration (\calibration.rs): Per-axis calibration structures with min/center/max raw values, deadzone support, and signed/unsigned normalization modes
  • VkbDeviceInfo table: 12-entry device info table (similar to Virpil's DEVICE_TABLE) for unified device lookup by PID
  • New device families: Added TRudder and StecsModernThrottle variants to VkbDeviceFamily enum
  • T-Rudder report layout: VKB_T_RUDDER_LAYOUT constant (3 axes, 0 buttons, 0 hats, 6-byte payload)
  • Profile PID: Wired community-estimated PID 0x0132 into the T-Rudder profile

Virpil Crate (flight-hotas-virpil)

  • New profiles: Added WarBRD, WarBRD-D, and MongoosT-50CM3 stick profiles to profiles.rs (5 axes each, 28 buttons, 8-way hat)
  • Multi-device detection (\multi_device.rs): Utility module for correlating multiple VIRPIL devices by category (Stick/Throttle/Pedals/Collective/Panel) with HOTAS and full-setup detection helpers
  • DeviceCategory enum: Classifies any VIRPIL PID into one of 5 hardware categories
  • SetupSummary: Describes which device categories are present with helper predicates

Testing

All new code includes comprehensive unit tests. All existing tests continue to pass.

VKB crate enhancements:
- Add T-Rudder Mk.IV/V pedal parser (3-axis, hall-effect sensors)
- Add axis calibration data structures (per-axis min/center/max/deadzone)
- Add VkbDeviceInfo table with 12 device entries for unified lookup
- Add T-Rudder and STECS Modern Throttle to VkbDeviceFamily enum
- Add T-Rudder report layout constant
- Wire T-Rudder profile PID (community-estimated 0x0132)

Virpil crate enhancements:
- Add WarBRD, WarBRD-D, and MongoosT-50CM3 device profiles
- Add multi-device detection module (base+grip+throttle+pedals correlation)
- Add DeviceCategory enum for grouping devices by role
- Add SetupSummary with HOTAS/full-setup detection helpers

All new code includes comprehensive unit tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 1, 2026 05:43
@gemini-code-assist
Copy link

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai
Copy link

coderabbitai bot commented Mar 1, 2026

Warning

Rate limit exceeded

@EffortlessSteven has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 28 minutes and 20 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between cd2e54d and 86d0545.

📒 Files selected for processing (8)
  • crates/flight-hotas-virpil/src/lib.rs
  • crates/flight-hotas-virpil/src/multi_device.rs
  • crates/flight-hotas-virpil/src/profiles.rs
  • crates/flight-hotas-vkb/src/calibration.rs
  • crates/flight-hotas-vkb/src/lib.rs
  • crates/flight-hotas-vkb/src/profiles.rs
  • crates/flight-hotas-vkb/src/protocol.rs
  • crates/flight-hotas-vkb/src/t_rudder.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/prosumer-protocols

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-free-for-open-source-projects

Review Summary by Qodo

Enhance VKB and Virpil HOTAS protocol support with pedals and multi-device detection

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add VKB T-Rudder pedal parser with 3-axis support and calibration framework
• Add Virpil multi-device detection module for setup categorization
• Add WarBRD, WarBRD-D, and MongoosT-50CM3 stick profiles to Virpil
• Expand VKB device info table with 12 entries for unified PID lookup
Diagram
flowchart LR
  VKB["VKB Enhancements"]
  VKB --> TR["T-Rudder Parser<br/>3-axis pedals"]
  VKB --> CAL["Axis Calibration<br/>min/center/max/deadzone"]
  VKB --> DT["Device Info Table<br/>12 PID entries"]
  
  VIRPIL["Virpil Enhancements"]
  VIRPIL --> PROF["New Stick Profiles<br/>WarBRD/MongoosT"]
  VIRPIL --> MD["Multi-Device Detection<br/>Category classification"]
  VIRPIL --> SS["Setup Summary<br/>HOTAS/full-setup helpers"]
Loading

Grey Divider

File Changes

1. crates/flight-hotas-vkb/src/t_rudder.rs ✨ Enhancement +243/-0

VKB T-Rudder pedal HID parser implementation

• New HID report parser for VKB T-Rudder Mk.IV/V pedals with 3 axes (left toe brake, right toe
 brake, rudder)
• Implements TRudderInputHandler with optional report ID stripping support
• Provides axis normalization: unsigned for brakes (0.0–1.0), signed for rudder (−1.0–1.0)
• Comprehensive unit tests covering edge cases, report ID handling, and boundary values

crates/flight-hotas-vkb/src/t_rudder.rs


2. crates/flight-hotas-vkb/src/calibration.rs ✨ Enhancement +291/-0

Axis calibration data structures and normalization

• New per-axis calibration structures with min/center/max raw values and deadzone support
• Implements AxisCalibration with signed/unsigned normalization modes for different axis types
• Provides DeviceCalibration for managing multi-axis device calibration sets
• Extensive unit tests for normalization logic, deadzone handling, and custom ranges

crates/flight-hotas-vkb/src/calibration.rs


3. crates/flight-hotas-vkb/src/protocol.rs ✨ Enhancement +244/-1

VKB device family classification and info table

• Add VkbDeviceFamily enum variants for T-Rudder and STECS Modern Throttle
• Add VKB_T_RUDDER_LAYOUT constant defining 3-axis, 0-button, 0-hat report structure
• Create VKB_DEVICE_TABLE with 12 device entries including axis/button/hat counts and min report
 sizes
• Implement vkb_device_info() lookup function and update from_pid() classification
• Add community-estimated T-Rudder PID constant (0x0132)

crates/flight-hotas-vkb/src/protocol.rs


View more (5)
4. crates/flight-hotas-vkb/src/lib.rs ✨ Enhancement +11/-2

VKB crate module and API exports

• Export new calibration and t_rudder modules
• Re-export calibration types (AxisCalibration, CalibratedNormMode, DeviceCalibration)
• Re-export T-Rudder parser types and constants
• Update protocol exports to include device table and lookup functions

crates/flight-hotas-vkb/src/lib.rs


5. crates/flight-hotas-vkb/src/profiles.rs ✨ Enhancement +2/-3

VKB T-Rudder profile PID configuration

• Wire T-Rudder PID (0x0132) into existing T-Rudder profile
• Add comprehensive unit tests for T-Rudder, WarBRD, and MongoosT profiles

crates/flight-hotas-vkb/src/profiles.rs


6. crates/flight-hotas-virpil/src/multi_device.rs ✨ Enhancement +290/-0

Virpil multi-device detection and categorization module

• New module for multi-device detection and VIRPIL device categorization
• Implement DeviceCategory enum classifying devices as Stick/Throttle/Pedals/Collective/Panel
• Implement DetectedDevice descriptor and SetupSummary for analyzing connected device sets
• Provide detect_setup() function to analyze PID arrays and pids_for_category() for reverse
 lookup
• Include helper predicates is_hotas() and is_full_setup() for common setup patterns
• Comprehensive unit tests covering all categories and setup detection scenarios

crates/flight-hotas-virpil/src/multi_device.rs


7. crates/flight-hotas-virpil/src/profiles.rs ✨ Enhancement +168/-0

Virpil WarBRD and MongoosT stick profiles

• Add WARBRD_AXES and WARBRD_PROFILE (PID 0x40CC) with 5 axes, 28 buttons, 8-way hat
• Add WARBRD_D_PROFILE (PID 0x43F5) with identical axis layout to WarBRD
• Add MONGOOST_AXES and MONGOOST_PROFILE (PID 0x4130) with shared firmware layout
• Update ALL_PROFILES lookup table to include three new profiles
• Add unit tests validating axis counts, button counts, hat types, and PID lookups

crates/flight-hotas-virpil/src/profiles.rs


8. crates/flight-hotas-virpil/src/lib.rs ✨ Enhancement +5/-0

Virpil crate multi-device module exports

• Export new multi_device module
• Re-export multi-device types: DetectedDevice, DeviceCategory, SetupSummary,
 detect_setup(), pids_for_category()

crates/flight-hotas-virpil/src/lib.rs


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link

qodo-free-for-open-source-projects bot commented Mar 1, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. STECS layout not mapped🐞 Bug ✓ Correctness
Description
VkbDeviceFamily::from_pid can return StecsModernThrottle, but report_layout_for_family has no
arm for it and falls back to VKB_JOYSTICK_STANDARD_LAYOUT (6 axes + hat, 21-byte payload). This
produces an incorrect layout for STECS Modern Throttle relative to the crate’s own STECS parser and
can cause mis-parsing or incorrect validation in downstream users of this API.
Code

crates/flight-hotas-vkb/src/protocol.rs[R157-163]

/// Return the expected report layout for a given device family.
pub fn report_layout_for_family(family: VkbDeviceFamily) -> VkbJoystickReportLayout {
   match family {
       VkbDeviceFamily::SemThq => VKB_SEM_THQ_LAYOUT,
+        VkbDeviceFamily::TRudder => VKB_T_RUDDER_LAYOUT,
       _ => VKB_JOYSTICK_STANDARD_LAYOUT,
   }
Evidence
The PR adds a new family classification for STECS Modern Throttle, but the report-layout lookup
function doesn’t handle it and returns the standard stick layout (6 axes + hat). This is
inconsistent with the STECS parser and even with the device table’s hat_count=0.

crates/flight-hotas-vkb/src/protocol.rs[70-88]
crates/flight-hotas-vkb/src/protocol.rs[157-163]
crates/flight-hotas-vkb/src/protocol.rs[126-134]
crates/flight-hotas-vkb/src/stecs_modern.rs[69-83]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`report_layout_for_family()` does not handle `VkbDeviceFamily::StecsModernThrottle`, so callers get the standard stick layout, which includes hats and 6 axes.
### Issue Context
The crate already has a dedicated STECS Modern Throttle parser (`stecs_modern`) with a different axis set and report layout expectations.
### Fix Focus Areas
- crates/flight-hotas-vkb/src/protocol.rs[157-163]
- crates/flight-hotas-vkb/src/protocol.rs[126-155]
- crates/flight-hotas-vkb/src/stecs_modern.rs[30-83]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Deadzone can produce NaN 🐞 Bug ⛯ Reliability
Description
AxisCalibration::normalize_* divides by (1.0 - deadzone) without enforcing the documented
deadzone bounds, so deadzone >= 1.0 (or NaN) can yield inf/NaN outputs. Those NaNs can silently
propagate into consumers and cause hard-to-debug behavior.
Code

crates/flight-hotas-vkb/src/calibration.rs[R83-125]

+    fn normalize_unsigned(&self, raw: u16) -> f32 {
+        let range = self.raw_max.saturating_sub(self.raw_min);
+        if range == 0 {
+            return 0.0;
+        }
+        let clamped = raw.clamp(self.raw_min, self.raw_max);
+        let norm = (clamped - self.raw_min) as f32 / range as f32;
+
+        if norm < self.deadzone {
+            0.0
+        } else {
+            // Rescale above deadzone to fill [0.0, 1.0]
+            ((norm - self.deadzone) / (1.0 - self.deadzone)).clamp(0.0, 1.0)
+        }
+    }
+
+    fn normalize_signed(&self, raw: u16) -> f32 {
+        let clamped = raw.clamp(self.raw_min, self.raw_max);
+
+        let norm = if clamped <= self.raw_center {
+            let range = self.raw_center.saturating_sub(self.raw_min);
+            if range == 0 {
+                0.0
+            } else {
+                -((self.raw_center - clamped) as f32 / range as f32)
+            }
+        } else {
+            let range = self.raw_max.saturating_sub(self.raw_center);
+            if range == 0 {
+                0.0
+            } else {
+                (clamped - self.raw_center) as f32 / range as f32
+            }
+        };
+
+        if norm.abs() < self.deadzone {
+            0.0
+        } else {
+            // Rescale outside deadzone to fill [−1.0, 1.0]
+            let sign = norm.signum();
+            let magnitude = (norm.abs() - self.deadzone) / (1.0 - self.deadzone);
+            (sign * magnitude).clamp(-1.0, 1.0)
+        }
Evidence
The code documents deadzone as 0.0..=0.5 but exposes it as a public field with no validation.
The normalization functions perform a division by (1.0 - deadzone); for invalid deadzones this can
produce inf/NaN, and clamp() will not reliably sanitize NaN.

crates/flight-hotas-vkb/src/calibration.rs[44-58]
crates/flight-hotas-vkb/src/calibration.rs[83-97]
crates/flight-hotas-vkb/src/calibration.rs[118-125]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`AxisCalibration` uses `deadzone` in denominators (`1.0 - deadzone`) but doesn’t validate that `deadzone` is within a safe range. Invalid values can produce `inf`/`NaN` and propagate downstream.
### Issue Context
`deadzone` is a public field, so callers can construct invalid calibrations even if docs say `0.0..=0.5`.
### Fix Focus Areas
- crates/flight-hotas-vkb/src/calibration.rs[44-58]
- crates/flight-hotas-vkb/src/calibration.rs[83-97]
- crates/flight-hotas-vkb/src/calibration.rs[118-125]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines 157 to 163
/// Return the expected report layout for a given device family.
pub fn report_layout_for_family(family: VkbDeviceFamily) -> VkbJoystickReportLayout {
match family {
VkbDeviceFamily::SemThq => VKB_SEM_THQ_LAYOUT,
VkbDeviceFamily::TRudder => VKB_T_RUDDER_LAYOUT,
_ => VKB_JOYSTICK_STANDARD_LAYOUT,
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Stecs layout not mapped 🐞 Bug ✓ Correctness

VkbDeviceFamily::from_pid can return StecsModernThrottle, but report_layout_for_family has no
arm for it and falls back to VKB_JOYSTICK_STANDARD_LAYOUT (6 axes + hat, 21-byte payload). This
produces an incorrect layout for STECS Modern Throttle relative to the crate’s own STECS parser and
can cause mis-parsing or incorrect validation in downstream users of this API.
Agent Prompt
### Issue description
`report_layout_for_family()` does not handle `VkbDeviceFamily::StecsModernThrottle`, so callers get the standard stick layout, which includes hats and 6 axes.

### Issue Context
The crate already has a dedicated STECS Modern Throttle parser (`stecs_modern`) with a different axis set and report layout expectations.

### Fix Focus Areas
- crates/flight-hotas-vkb/src/protocol.rs[157-163]
- crates/flight-hotas-vkb/src/protocol.rs[126-155]
- crates/flight-hotas-vkb/src/stecs_modern.rs[30-83]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e585ef774

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

match family {
VkbDeviceFamily::SemThq => VKB_SEM_THQ_LAYOUT,
VkbDeviceFamily::TRudder => VKB_T_RUDDER_LAYOUT,
_ => VKB_JOYSTICK_STANDARD_LAYOUT,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Handle STECS family in layout dispatch

report_layout_for_family has no VkbDeviceFamily::StecsModernThrottle arm, so STECS devices fall through to VKB_JOYSTICK_STANDARD_LAYOUT (hat byte + 21-byte payload). In the same module, STECS entries in VKB_DEVICE_TABLE are declared with hat_count: 0 and min_report_bytes: 20, so callers that use the family layout for parsing/validation will compute the wrong offsets and can reject or misinterpret STECS reports.

Useful? React with 👍 / 👎.

Comment on lines +283 to +286
axis_count: 6,
max_buttons: 64,
hat_count: 0,
min_report_bytes: 20,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align STECS metadata with parser contract

The STECS Modern Mini/Max table rows advertise axis_count: 6 and min_report_bytes: 20, but parse_stecs_mt_report (stecs_modern.rs) parses four axes and accepts 17 bytes total (16-byte payload after report ID). This inconsistency makes vkb_device_info unreliable for sizing axis storage or report-length prechecks, which can cause valid STECS input to be rejected or mapped incorrectly when metadata-driven paths are used.

Useful? React with 👍 / 👎.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds expanded VKB and VIRPIL HOTAS device/protocol support within their respective crates, including new device-specific parsers, device lookup metadata, and multi-device setup detection utilities.

Changes:

  • Introduces a VKB T-Rudder HID report parser plus associated report layout, PID plumbing, and profile updates.
  • Adds VKB axis calibration types (per-axis + per-device) with normalization helpers and unit tests.
  • Extends VIRPIL with additional stick profiles and a multi-device detection module (category classification + setup summary helpers).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
crates/flight-hotas-vkb/src/t_rudder.rs New VKB T-Rudder HID report parser + tests.
crates/flight-hotas-vkb/src/protocol.rs Adds T-Rudder/STECS Modern family support, a VKB device info table, and T-Rudder report layout.
crates/flight-hotas-vkb/src/profiles.rs Wires T-Rudder PID into the built-in profile registry.
crates/flight-hotas-vkb/src/lib.rs Exposes new VKB modules and re-exports new public types/constants.
crates/flight-hotas-vkb/src/calibration.rs New calibration structures and normalization logic + tests.
crates/flight-hotas-virpil/src/profiles.rs Adds WarBRD / WarBRD-D / MongoosT-50CM3 stick profiles + lookup tests.
crates/flight-hotas-virpil/src/multi_device.rs New VIRPIL multi-device categorization and setup detection utilities + tests.
crates/flight-hotas-virpil/src/lib.rs Registers the new VIRPIL multi_device module and re-exports its API.

Comment on lines +91 to +96
if norm < self.deadzone {
0.0
} else {
// Rescale above deadzone to fill [0.0, 1.0]
((norm - self.deadzone) / (1.0 - self.deadzone)).clamp(0.0, 1.0)
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deadzone is documented as 0.0..=0.5, but it’s not validated/clamped. If a caller constructs AxisCalibration with deadzone >= 1.0 (or negative), the rescale path divides by (1.0 - deadzone) which can yield inf/NaN and propagate through clamp(). Consider clamping deadzone to a safe range (e.g., 0.0.. < 1.0) inside normalize_*, or adding a constructor/validation method and making the fields private to enforce the invariant.

Copilot uses AI. Check for mistakes.
Comment on lines 1054 to 1061
/// Note: The Mk.V PID is not yet confirmed; this profile uses the Mk.IV layout
/// which is expected to be identical.
pub fn t_rudder_profile() -> VkbDeviceProfile {
VkbDeviceProfile {
device_name: "VKB T-Rudder Mk.IV",
vid: VKB_VENDOR_ID,
// T-Rudder PID not in device_support.rs yet; leave empty for now.
// Users should match by descriptor discovery or explicit configuration.
pids: &[],
pids: &[VKB_T_RUDDER_MK5_PID],
axes: &T_RUDDER_AXES,
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t_rudder_profile() advertises Mk.IV in device_name/notes but matches by VKB_T_RUDDER_MK5_PID (Mk.V community estimate). This is likely to confuse users and downstream UI/logging. Consider renaming the profile/device name and notes to “Mk.IV/Mk.V” (or “Mk.V (est.)”) to reflect the PID being matched.

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +176
/// Complete VID/PID entry for a VKB device.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct VkbDeviceInfo {
/// USB Product ID.
pub pid: u16,
/// Device family.
pub family: VkbDeviceFamily,
/// Human-readable product name.
pub name: &'static str,
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment “Complete VID/PID entry for a VKB device” is misleading: VkbDeviceInfo only stores pid (VID is implicitly VKB_VENDOR_ID). Consider adjusting the docstring to avoid implying VID is stored, or add a vid field if callers are expected to treat this as a full VID/PID tuple.

Copilot uses AI. Check for mistakes.
Comment on lines +125 to +140
// ─── Shared helpers (same as protocol.rs) ─────────────────────────────────────

fn le_u16(bytes: &[u8], offset: usize) -> u16 {
let low = bytes.get(offset).copied().unwrap_or(0);
let high = bytes.get(offset + 1).copied().unwrap_or(0);
u16::from_le_bytes([low, high])
}

fn normalize_u16(raw: u16) -> f32 {
(raw as f32 / u16::MAX as f32).clamp(0.0, 1.0)
}

fn normalize_signed(raw: u16) -> f32 {
((raw as f32 / 32767.5) - 1.0).clamp(-1.0, 1.0)
}

Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file redefines le_u16, normalize_u16, and normalize_signed, which already exist (with identical implementations) in protocol.rs and input.rs. Adding a third copy increases the chance of these helpers drifting over time. Consider moving these helpers into a shared pub(crate) utility module and reusing them from all parsers.

Suggested change
// ─── Shared helpers (same as protocol.rs) ─────────────────────────────────────
fn le_u16(bytes: &[u8], offset: usize) -> u16 {
let low = bytes.get(offset).copied().unwrap_or(0);
let high = bytes.get(offset + 1).copied().unwrap_or(0);
u16::from_le_bytes([low, high])
}
fn normalize_u16(raw: u16) -> f32 {
(raw as f32 / u16::MAX as f32).clamp(0.0, 1.0)
}
fn normalize_signed(raw: u16) -> f32 {
((raw as f32 / 32767.5) - 1.0).clamp(-1.0, 1.0)
}
// ─── Shared helpers (reused from protocol.rs) ─────────────────────────────────
use crate::protocol::{le_u16, normalize_signed, normalize_u16};

Copilot uses AI. Check for mistakes.
Comment on lines +374 to +410
pub static MONGOOST_AXES: &[AxisDescriptor] = &[
AxisDescriptor {
index: 0,
role: AxisRole::StickX,
label: "X (roll)",
centred: true,
},
AxisDescriptor {
index: 1,
role: AxisRole::StickY,
label: "Y (pitch)",
centred: true,
},
AxisDescriptor {
index: 2,
role: AxisRole::Twist,
label: "Z (twist)",
centred: true,
},
AxisDescriptor {
index: 3,
role: AxisRole::SecondaryRotary,
label: "SZ (secondary rotary)",
centred: false,
},
AxisDescriptor {
index: 4,
role: AxisRole::SlewLever,
label: "SL (slew lever)",
centred: false,
},
];

static MONGOOST_HATS: &[HatDescriptor] = &[HatDescriptor {
label: "Main hat",
hat_type: HatType::EightWay,
}];
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MONGOOST_AXES/MONGOOST_HATS are byte-for-byte identical to WARBRD_AXES/WARBRD_HATS (and the docs explicitly say the layouts are identical). Consider reusing the same slice(s) (e.g., aliasing MONGOOST_AXES to WARBRD_AXES) to avoid duplicated definitions that could drift if one is updated later.

Suggested change
pub static MONGOOST_AXES: &[AxisDescriptor] = &[
AxisDescriptor {
index: 0,
role: AxisRole::StickX,
label: "X (roll)",
centred: true,
},
AxisDescriptor {
index: 1,
role: AxisRole::StickY,
label: "Y (pitch)",
centred: true,
},
AxisDescriptor {
index: 2,
role: AxisRole::Twist,
label: "Z (twist)",
centred: true,
},
AxisDescriptor {
index: 3,
role: AxisRole::SecondaryRotary,
label: "SZ (secondary rotary)",
centred: false,
},
AxisDescriptor {
index: 4,
role: AxisRole::SlewLever,
label: "SL (slew lever)",
centred: false,
},
];
static MONGOOST_HATS: &[HatDescriptor] = &[HatDescriptor {
label: "Main hat",
hat_type: HatType::EightWay,
}];
pub static MONGOOST_AXES: &[AxisDescriptor] = WARBRD_AXES;
static MONGOOST_HATS: &[HatDescriptor] = WARBRD_HATS;

Copilot uses AI. Check for mistakes.
EffortlessSteven and others added 2 commits March 1, 2026 01:05
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add StecsModernThrottle arm to report_layout_for_family with new
  VKB_STECS_MODERN_LAYOUT constant (4 axes, 2 button words, 16 bytes)
- Fix STECS Modern Mini/Max metadata: axis_count 6->4, min_report_bytes 20->17
  to match parse_stecs_mt_report expectations
- Clamp deadzone to 0.0..0.999 in normalize_unsigned and normalize_signed
  to prevent inf/NaN from division by zero when deadzone == 1.0
- Rename T-Rudder profile from Mk.IV to Mk.IV/V since it matches
  VKB_T_RUDDER_MK5_PID; update notes accordingly
- Fix VkbDeviceInfo docstring: struct stores PID only, not VID/PID
- Deduplicate le_u16/normalize_u16/normalize_signed helpers: make them
  pub(crate) in protocol.rs and import in t_rudder.rs
- Replace duplicate MONGOOST_AXES/MONGOOST_HATS with aliases to
  WARBRD_AXES/WARBRD_HATS (identical axis layout per shared VPC firmware)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@qodo-free-for-open-source-projects

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: Test Suite (windows-latest, stable)

Failed stage: Run tests [❌]

Failed test name: snapshot_alpha_yoke_full_right_roll

Failure summary:

The action failed during cargo test --all-features --workspace --lib --tests --exclude
flight-hub-examples because an Insta snapshot test failed in the flight-hotas-honeycomb crate.
-
Failed test: snapshot_alpha_yoke_full_right_roll in tests/snapshot_tests.rs:64 (crate
flight-hotas-honeycomb, test binary snapshot_tests).
- Reason: snapshot mismatch for
alpha_yoke_full_right_roll: the expected roll value was 1.0, but the new output was 0.9995117,
causing insta to panic (insta-1.46.3/src/runtime.rs:719) and the test process to exit with code 101.

- The log suggests updating/reviewing snapshots via cargo insta test if the new output is correct.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

176:  RUST_BACKTRACE: 1
177:  targets: 
178:  components: rustfmt, clippy
179:  ##[endgroup]
180:  ##[group]Run : set $CARGO_HOME
181:  �[36;1m: set $CARGO_HOME�[0m
182:  �[36;1mecho CARGO_HOME=${CARGO_HOME:-"$USERPROFILE\.cargo"} >> $GITHUB_ENV�[0m
183:  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
184:  env:
185:  CARGO_TERM_COLOR: always
186:  RUST_BACKTRACE: 1
187:  ##[endgroup]
188:  ##[group]Run : install rustup if needed on windows
189:  �[36;1m: install rustup if needed on windows�[0m
190:  �[36;1mif ! command -v rustup &>/dev/null; then�[0m
191:  �[36;1m  curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused --location --silent --show-error --fail https://win.rustup.rs/x86_64 --output 'D:\a\_temp\rustup-init.exe'�[0m
192:  �[36;1m  'D:\a\_temp\rustup-init.exe' --default-toolchain none --no-modify-path -y�[0m
...

264:  �[36;1m  if rustc +stable --version --verbose | grep -q '^release: 1\.6[89]\.'; then�[0m
265:  �[36;1m    touch "D:\a\_temp"/.implicit_cargo_registries_crates_io_protocol || true�[0m
266:  �[36;1m    echo CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse >> $GITHUB_ENV�[0m
267:  �[36;1m  elif rustc +stable --version --verbose | grep -q '^release: 1\.6[67]\.'; then�[0m
268:  �[36;1m    touch "D:\a\_temp"/.implicit_cargo_registries_crates_io_protocol || true�[0m
269:  �[36;1m    echo CARGO_REGISTRIES_CRATES_IO_PROTOCOL=git >> $GITHUB_ENV�[0m
270:  �[36;1m  fi�[0m
271:  �[36;1mfi�[0m
272:  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
273:  env:
274:  CARGO_TERM_COLOR: always
275:  RUST_BACKTRACE: 1
276:  CARGO_HOME: C:\Users\runneradmin\.cargo
277:  CARGO_INCREMENTAL: 0
278:  ##[endgroup]
279:  ##[group]Run : work around spurious network errors in curl 8.0
280:  �[36;1m: work around spurious network errors in curl 8.0�[0m
281:  �[36;1m# https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/timeout.20investigation�[0m
...

449:  - D:\a\OpenFlight\OpenFlight\examples\Cargo.toml
450:  - D:\a\OpenFlight\OpenFlight\installer\Cargo.toml
451:  - D:\a\OpenFlight\OpenFlight\specs\Cargo.toml
452:  - D:\a\OpenFlight\OpenFlight\xtask\Cargo.toml
453:  ##[endgroup]
454:  ... Restoring cache ...
455:  No cache found.
456:  ##[group]Run cargo fmt --all -- --check
457:  �[36;1mcargo fmt --all -- --check�[0m
458:  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
459:  env:
460:  CARGO_TERM_COLOR: always
461:  RUST_BACKTRACE: 1
462:  CARGO_HOME: C:\Users\runneradmin\.cargo
463:  CARGO_INCREMENTAL: 0
464:  CACHE_ON_FAILURE: false
465:  ##[endgroup]
466:  ##[group]Run cargo clippy --workspace --all-features --lib --tests --exclude flight-hub-examples
467:  �[36;1mcargo clippy --workspace --all-features --lib --tests --exclude flight-hub-examples�[0m
468:  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
469:  env:
470:  CARGO_TERM_COLOR: always
471:  RUST_BACKTRACE: 1
472:  CARGO_HOME: C:\Users\runneradmin\.cargo
473:  CARGO_INCREMENTAL: 0
474:  CACHE_ON_FAILURE: false
475:  ##[endgroup]
...

584:  �[1m�[92m  Downloaded�[0m tokio-tungstenite v0.28.0
585:  �[1m�[92m  Downloaded�[0m tokio-test v0.4.5
586:  �[1m�[92m  Downloaded�[0m protoc-bin-vendored-linux-ppcle_64 v3.2.0
587:  �[1m�[92m  Downloaded�[0m tokio-stream v0.1.18
588:  �[1m�[92m  Downloaded�[0m tokio-rustls v0.26.4
589:  �[1m�[92m  Downloaded�[0m tokio-macros v2.6.0
590:  �[1m�[92m  Downloaded�[0m protoc-bin-vendored-win32 v3.2.0
591:  �[1m�[92m  Downloaded�[0m protoc-bin-vendored-linux-x86_64 v3.2.0
592:  �[1m�[92m  Downloaded�[0m tinyvec_macros v0.1.1
593:  �[1m�[92m  Downloaded�[0m tinyvec v1.10.0
594:  �[1m�[92m  Downloaded�[0m tinytemplate v1.2.1
595:  �[1m�[92m  Downloaded�[0m tinystr v0.8.2
596:  �[1m�[92m  Downloaded�[0m time-macros v0.2.27
597:  �[1m�[92m  Downloaded�[0m time-core v0.1.8
598:  �[1m�[92m  Downloaded�[0m thread_local v1.1.9
599:  �[1m�[92m  Downloaded�[0m thiserror-impl v2.0.18
600:  �[1m�[92m  Downloaded�[0m protoc-bin-vendored-linux-x86_32 v3.2.0
601:  �[1m�[92m  Downloaded�[0m protoc-bin-vendored-linux-s390_64 v3.2.0
602:  �[1m�[92m  Downloaded�[0m thiserror v2.0.18
603:  �[1m�[92m  Downloaded�[0m textwrap v0.16.2
...

615:  �[1m�[92m  Downloaded�[0m utf-8 v0.7.6
616:  �[1m�[92m  Downloaded�[0m unsafe-libyaml v0.2.11
617:  �[1m�[92m  Downloaded�[0m unicode-xid v0.2.6
618:  �[1m�[92m  Downloaded�[0m unicode-linebreak v0.1.5
619:  �[1m�[92m  Downloaded�[0m unicode-ident v1.0.24
620:  �[1m�[92m  Downloaded�[0m unicode-general-category v1.1.0
621:  �[1m�[92m  Downloaded�[0m unarray v0.1.4
622:  �[1m�[92m  Downloaded�[0m typetag-impl v0.2.21
623:  �[1m�[92m  Downloaded�[0m toml_datetime v0.6.11
624:  �[1m�[92m  Downloaded�[0m shlex v1.3.0
625:  �[1m�[92m  Downloaded�[0m sharded-slab v0.1.7
626:  �[1m�[92m  Downloaded�[0m sha2 v0.10.9
627:  �[1m�[92m  Downloaded�[0m serde_yaml_ng v0.10.0
628:  �[1m�[92m  Downloaded�[0m serde_urlencoded v0.7.1
629:  �[1m�[92m  Downloaded�[0m serde_spanned v0.6.9
630:  �[1m�[92m  Downloaded�[0m serde_path_to_error v0.1.20
631:  �[1m�[92m  Downloaded�[0m serde_derive v1.0.228
...

699:  �[1m�[92m  Downloaded�[0m icu_normalizer_data v2.1.1
700:  �[1m�[92m  Downloaded�[0m icu_normalizer v2.1.1
701:  �[1m�[92m  Downloaded�[0m icu_locale_core v2.1.1
702:  �[1m�[92m  Downloaded�[0m icu_collections v2.1.1
703:  �[1m�[92m  Downloaded�[0m half v2.7.1
704:  �[1m�[92m  Downloaded�[0m gherkin v0.15.0
705:  �[1m�[92m  Downloaded�[0m getrandom v0.4.1
706:  �[1m�[92m  Downloaded�[0m getrandom v0.3.4
707:  �[1m�[92m  Downloaded�[0m getrandom v0.2.17
708:  �[1m�[92m  Downloaded�[0m rand_xorshift v0.4.0
709:  �[1m�[92m  Downloaded�[0m rand_core v0.9.5
710:  �[1m�[92m  Downloaded�[0m rand_core v0.6.4
711:  �[1m�[92m  Downloaded�[0m rand_chacha v0.9.0
712:  �[1m�[92m  Downloaded�[0m quote v1.0.44
713:  �[1m�[92m  Downloaded�[0m quinn-udp v0.5.14
714:  �[1m�[92m  Downloaded�[0m quick-error v1.2.3
715:  �[1m�[92m  Downloaded�[0m pulldown-cmark-to-cmark v22.0.0
...

887:  �[1m�[92m  Downloaded�[0m adler2 v2.0.1
888:  �[1m�[92m  Downloaded�[0m cobs v0.3.0
889:  �[1m�[92m  Downloaded�[0m ciborium-io v0.2.2
890:  �[1m�[92m  Downloaded�[0m cfg_aliases v0.2.1
891:  �[1m�[92m  Downloaded�[0m bit-set v0.8.0
892:  �[1m�[92m  Downloaded�[0m anstyle-wincon v3.0.11
893:  �[1m�[92m  Downloaded�[0m alloca v0.4.0
894:  �[1m�[92m  Downloaded�[0m windows v0.62.2
895:  �[1m�[92m Downloading�[0m crates ...
896:  �[1m�[92m  Downloaded�[0m nix v0.31.2
897:  �[1m�[92m   Compiling�[0m proc-macro2 v1.0.106
898:  �[1m�[92m   Compiling�[0m quote v1.0.44
899:  �[1m�[92m   Compiling�[0m unicode-ident v1.0.24
900:  �[1m�[92m   Compiling�[0m serde_core v1.0.228
901:  �[1m�[92m   Compiling�[0m serde v1.0.228
902:  �[1m�[92m   Compiling�[0m thiserror v2.0.18
903:  �[1m�[92m   Compiling�[0m getrandom v0.3.4
...

917:  �[1m�[92m    Checking�[0m pin-project-lite v0.2.17
918:  �[1m�[92m   Compiling�[0m version_check v0.9.5
919:  �[1m�[92m    Checking�[0m log v0.4.29
920:  �[1m�[92m    Checking�[0m tracing-core v0.1.36
921:  �[1m�[92m   Compiling�[0m typenum v1.19.0
922:  �[1m�[92m   Compiling�[0m generic-array v0.14.7
923:  �[1m�[92m    Checking�[0m regex-syntax v0.8.10
924:  �[1m�[92m    Checking�[0m fnv v1.0.7
925:  �[1m�[92m    Checking�[0m rand_core v0.9.5
926:  �[1m�[92m    Checking�[0m fastrand v2.3.0
927:  �[1m�[92m    Checking�[0m bitflags v2.11.0
928:  �[1m�[92m    Checking�[0m bit-vec v0.8.0
929:  �[1m�[92m    Checking�[0m memchr v2.8.0
930:  �[1m�[92m    Checking�[0m bit-set v0.8.0
931:  �[1m�[92m    Checking�[0m wait-timeout v0.2.1
932:  �[1m�[92m    Checking�[0m quick-error v1.2.3
933:  �[1m�[92m    Checking�[0m rand_xorshift v0.4.0
934:  �[1m�[92m    Checking�[0m unarray v0.1.4
935:  �[1m�[92m    Checking�[0m itoa v1.0.17
936:  �[1m�[92m   Compiling�[0m anyhow v1.0.102
937:  �[1m�[92m   Compiling�[0m crossbeam-utils v0.8.21
938:  �[1m�[92m    Checking�[0m windows-targets v0.53.5
939:  �[1m�[92m    Checking�[0m windows-sys v0.60.2
940:  �[1m�[92m   Compiling�[0m semver v1.0.27
941:  �[1m�[92m    Checking�[0m bytes v1.11.1
942:  �[1m�[92m   Compiling�[0m rustc_version v0.4.1
943:  �[1m�[92m    Checking�[0m socket2 v0.6.2
944:  �[1m�[92m   Compiling�[0m heapless v0.7.17
945:  �[1m�[92m   Compiling�[0m serde_derive v1.0.228
946:  �[1m�[92m   Compiling�[0m thiserror-impl v2.0.18
947:  �[1m�[92m   Compiling�[0m tracing-attributes v0.1.31
...

1180:  �[1m�[92m   Compiling�[0m protoc-bin-vendored-linux-s390_64 v3.2.0
1181:  �[1m�[92m   Compiling�[0m protoc-bin-vendored-linux-x86_32 v3.2.0
1182:  �[1m�[92m   Compiling�[0m protoc-bin-vendored-linux-ppcle_64 v3.2.0
1183:  �[1m�[92m   Compiling�[0m protoc-bin-vendored-win32 v3.2.0
1184:  �[1m�[92m   Compiling�[0m protoc-bin-vendored-macos-aarch_64 v3.2.0
1185:  �[1m�[92m   Compiling�[0m protoc-bin-vendored-linux-x86_64 v3.2.0
1186:  �[1m�[92m   Compiling�[0m protoc-bin-vendored-linux-aarch_64 v3.2.0
1187:  �[1m�[92m   Compiling�[0m protoc-bin-vendored-macos-x86_64 v3.2.0
1188:  �[1m�[92m    Checking�[0m tracing-subscriber v0.3.22
1189:  �[1m�[92m   Compiling�[0m protoc-bin-vendored v3.2.0
1190:  �[1m�[92m   Compiling�[0m tonic-prost-build v0.14.5
1191:  �[1m�[92m    Checking�[0m tokio-tungstenite v0.28.0
1192:  �[1m�[92m    Checking�[0m axum-core v0.5.6
1193:  �[1m�[92m    Checking�[0m serde_urlencoded v0.7.1
1194:  �[1m�[92m    Checking�[0m futures-executor v0.3.32
1195:  �[1m�[92m    Checking�[0m serde_path_to_error v0.1.20
1196:  �[1m�[92m    Checking�[0m matchit v0.8.4
...

1468:  �[1m�[96m--> �[0mcrates\flight-watchdog\src\lib.rs:1134:9
1469:  �[1m�[96m|�[0m
1470:  �[1m�[96m1134�[0m �[1m�[96m|�[0m         config.enable_nan_guards = true;
1471:  �[1m�[96m|�[0m         �[1m�[93m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^�[0m
1472:  �[1m�[96m|�[0m
1473:  �[1m�[92mnote�[0m: consider initializing the variable with `WatchdogConfig { enable_nan_guards: true, ..Default::default() }` and removing relevant reassignments
1474:  �[1m�[96m--> �[0mcrates\flight-watchdog\src\lib.rs:1133:9
1475:  �[1m�[96m|�[0m
1476:  �[1m�[96m1133�[0m �[1m�[96m|�[0m         let mut config = WatchdogConfig::default();
1477:  �[1m�[96m|�[0m         �[1m�[92m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^�[0m
1478:  �[1m�[96m= �[0m�[1m�[97mhelp�[0m: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.93.0/index.html#field_reassign_with_default
1479:  �[1m�[96m= �[0m�[1m�[97mnote�[0m: `#[warn(clippy::field_reassign_with_default)]` on by default
1480:  �[1m�[93mwarning�[0m�[1m�[97m: field assignment outside of initializer for an instance created with Default::default()�[0m
1481:  �[1m�[96m--> �[0mcrates\flight-watchdog\src\lib.rs:1158:9
1482:  �[1m�[96m|�[0m
1483:  �[1m�[96m1158�[0m �[1m�[96m|�[0m         config.max_consecutive_failures = 2; // Lower threshold for testing
1484:  �[1m�[96m|�[0m         �[1m�[93m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^�[0m
1485:  �[1m�[96m|�[0m
1486:  �[1m�[92mnote�[0m: consider initializing the variable with `WatchdogConfig { max_consecutive_failures: 2, ..Default::default() }` and removing relevant reassignments
1487:  �[1m�[96m--> �[0mcrates\flight-watchdog\src\lib.rs:1157:9
...

1605:  �[1m�[93mwarning�[0m: `flight-axis` (test "mixer_tests") generated 1 warning (run `cargo clippy --fix --test "mixer_tests" -p flight-axis` to apply 1 suggestion)
1606:  �[1m�[93mwarning[E0133]�[0m�[1m�[97m: call to unsafe function `flight_axis::Node::step_soa` is unsafe and requires unsafe block�[0m
1607:  �[1m�[96m--> �[0mcrates\flight-axis\tests\detent_tests.rs:25:5
1608:  �[1m�[96m|�[0m
1609:  �[1m�[96m25�[0m �[1m�[96m|�[0m     node.step_soa(frame, state_ptr);
1610:  �[1m�[96m|�[0m     �[1m�[93m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^�[0m �[1m�[93mcall to unsafe function�[0m
1611:  �[1m�[96m|�[0m
1612:  �[1m�[96m= �[0m�[1m�[97mnote�[0m: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html>
1613:  �[1m�[96m= �[0m�[1m�[97mnote�[0m: consult the function's documentation for information on how to avoid undefined behavior
1614:  �[1m�[92mnote�[0m: an unsafe function restricts its caller, but its body is safe by default
1615:  �[1m�[96m--> �[0mcrates\flight-axis\tests\detent_tests.rs:23:1
1616:  �[1m�[96m|�[0m
1617:  �[1m�[96m23�[0m �[1m�[96m|�[0m unsafe fn process_frame_soa(node: &DetentNode, frame: &mut AxisFrame, state: &mut DetentState) {
1618:  �[1m�[96m|�[0m �[1m�[92m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^�[0m
1619:  �[1m�[96m= �[0m�[1m�[97mnote�[0m: `#[warn(unsafe_op_in_unsafe_fn)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
1620:  �[1m�[97mFor more information about this error, try `rustc --explain E0133`.�[0m
1621:  �[1m�[93mwarning�[0m: `flight-axis` (test "detent_tests") generated 1 warning (run `cargo clippy --fix --test "detent_tests" -p flight-axis` to apply 1 suggestion)
...

1812:  �[1m�[96m--> �[0mcrates\flight-core\src\lib.rs:131:30
1813:  �[1m�[96m|�[0m
1814:  �[1m�[96m131�[0m �[1m�[96m|�[0m         let r: Result<u32> = Ok(42);
1815:  �[1m�[96m|�[0m                              �[1m�[96m^^^^^^�[0m
1816:  �[1m�[96m= �[0m�[1m�[97mhelp�[0m: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.93.0/index.html#unnecessary_literal_unwrap
1817:  �[1m�[96m= �[0m�[1m�[97mnote�[0m: `#[warn(clippy::unnecessary_literal_unwrap)]` on by default
1818:  �[1m�[93mwarning�[0m�[1m�[97m: used `unwrap_err()` on `Err` value�[0m
1819:  �[1m�[96m--> �[0mcrates\flight-core\src\lib.rs:136:17
1820:  �[1m�[96m|�[0m
1821:  �[1m�[96m136�[0m �[1m�[96m|�[0m         assert!(e.unwrap_err().to_string().contains("Rules validation"));
1822:  �[1m�[96m|�[0m                 �[1m�[93m^^^^^^^^^^^^^^�[0m
1823:  �[1m�[96m|�[0m
1824:  �[1m�[96mhelp�[0m: remove the `Err` and `unwrap_err()`
1825:  �[1m�[96m--> �[0mcrates\flight-core\src\lib.rs:134:30
1826:  �[1m�[96m|�[0m
1827:  �[1m�[96m134�[0m �[1m�[96m|�[0m         let e: Result<u32> = Err(FlightError::RulesValidation("bad rule".to_string()));
1828:  �[1m�[96m|�[0m                              �[1m�[96m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^�[0m
...

2185:  �[36;1m# Apply strict warnings to core crates that must maintain high quality�[0m
2186:  �[36;1mcargo clippy -p flight-core --lib -- $STRICT_FLAGS�[0m
2187:  �[36;1mcargo clippy -p flight-axis --lib -- $STRICT_FLAGS�[0m
2188:  �[36;1mcargo clippy -p flight-bus --lib -- $STRICT_FLAGS�[0m
2189:  �[36;1mcargo clippy -p flight-hid --lib -- $STRICT_FLAGS�[0m
2190:  �[36;1mcargo clippy -p flight-ipc --lib -- $STRICT_FLAGS�[0m
2191:  �[36;1mcargo clippy -p flight-service --lib -- $STRICT_FLAGS�[0m
2192:  �[36;1mcargo clippy -p flight-simconnect --lib -- $STRICT_FLAGS�[0m
2193:  �[36;1mcargo clippy -p flight-panels --lib -- $STRICT_FLAGS�[0m
2194:  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
2195:  env:
2196:  CARGO_TERM_COLOR: always
2197:  RUST_BACKTRACE: 1
2198:  CARGO_HOME: C:\Users\runneradmin\.cargo
2199:  CARGO_INCREMENTAL: 0
2200:  CACHE_ON_FAILURE: false
2201:  ##[endgroup]
...

2209:  �[1m�[92m   Compiling�[0m num-traits v0.2.19
2210:  �[1m�[92m    Checking�[0m crossbeam-epoch v0.9.18
2211:  �[1m�[92m    Checking�[0m aho-corasick v1.1.4
2212:  �[1m�[92m    Checking�[0m mio v1.1.1
2213:  �[1m�[92m    Checking�[0m hashbrown v0.16.1
2214:  �[1m�[92m    Checking�[0m regex-automata v0.4.14
2215:  �[1m�[92m    Checking�[0m indexmap v2.13.0
2216:  �[1m�[92m    Checking�[0m crossbeam-deque v0.8.6
2217:  �[1m�[92m    Checking�[0m crossbeam-channel v0.5.15
2218:  �[1m�[92m    Checking�[0m crossbeam-queue v0.3.12
2219:  �[1m�[92m    Checking�[0m tempfile v3.26.0
2220:  �[1m�[92m    Checking�[0m crossbeam v0.8.4
2221:  �[1m�[92m    Checking�[0m flight-metrics v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-metrics)
2222:  �[1m�[92m    Checking�[0m regex v1.12.3
2223:  �[1m�[92m   Compiling�[0m serde_derive v1.0.228
2224:  �[1m�[92m   Compiling�[0m thiserror-impl v2.0.18
2225:  �[1m�[92m   Compiling�[0m windows-interface v0.59.3
2226:  �[1m�[92m   Compiling�[0m windows-implement v0.60.2
2227:  �[1m�[92m   Compiling�[0m tracing-attributes v0.1.31
2228:  �[1m�[92m    Checking�[0m windows-core v0.62.2
2229:  �[1m�[92m   Compiling�[0m tokio-macros v2.6.0
2230:  �[1m�[92m    Checking�[0m thiserror v2.0.18
2231:  �[1m�[92m    Checking�[0m windows-numerics v0.3.1
...

2451:  �[1m�[92m    Checking�[0m flight-panels-saitek v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-panels-saitek)
2452:  �[1m�[92m    Checking�[0m flight-panels v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-panels)
2453:  �[1m�[92m    Finished�[0m `dev` profile [unoptimized + debuginfo] target(s) in 1.15s
2454:  ##[group]Run echo "🔍 Running file descriptor safety tests for public API crates..."
2455:  �[36;1mecho "🔍 Running file descriptor safety tests for public API crates..."�[0m
2456:  �[36;1m# Test that public API crates use typed file descriptors instead of RawFd�[0m
2457:  �[36;1mcargo test -p flight-hid fd_safety_tests�[0m
2458:  �[36;1mcargo test -p flight-ipc fd_safety_tests�[0m
2459:  �[36;1mcargo test -p flight-service fd_safety_tests�[0m
2460:  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
2461:  env:
2462:  CARGO_TERM_COLOR: always
2463:  RUST_BACKTRACE: 1
2464:  CARGO_HOME: C:\Users\runneradmin\.cargo
2465:  CARGO_INCREMENTAL: 0
2466:  CACHE_ON_FAILURE: false
2467:  ##[endgroup]
2468:  🔍 Running file descriptor safety tests for public API crates...
2469:  �[1m�[92m   Compiling�[0m windows-link v0.2.1
2470:  �[1m�[92m   Compiling�[0m serde_core v1.0.228
2471:  �[1m�[92m   Compiling�[0m cfg-if v1.0.4
2472:  �[1m�[92m   Compiling�[0m once_cell v1.21.3
2473:  �[1m�[92m   Compiling�[0m windows-sys v0.61.2
2474:  �[1m�[92m   Compiling�[0m thiserror v2.0.18
2475:  �[1m�[92m   Compiling�[0m typenum v1.19.0
...

2537:  �[1m�[92m   Compiling�[0m toml_edit v0.22.27
2538:  �[1m�[92m   Compiling�[0m chrono v0.4.44
2539:  �[1m�[92m   Compiling�[0m flight-process-detection v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-process-detection)
2540:  �[1m�[92m   Compiling�[0m flight-profile v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-profile)
2541:  �[1m�[92m   Compiling�[0m hex v0.4.3
2542:  �[1m�[92m   Compiling�[0m flight-security v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-security)
2543:  �[1m�[92m   Compiling�[0m ppv-lite86 v0.2.21
2544:  �[1m�[92m   Compiling�[0m flight-session v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-session)
2545:  �[1m�[92m   Compiling�[0m toml v0.8.23
2546:  �[1m�[92m   Compiling�[0m flight-blackbox v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-blackbox)
2547:  �[1m�[92m   Compiling�[0m flight-writers v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-writers)
2548:  �[1m�[92m   Compiling�[0m windows-sys v0.59.0
2549:  �[1m�[92m   Compiling�[0m flight-watchdog v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-watchdog)
2550:  �[1m�[92m   Compiling�[0m flight-units v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-units)
2551:  �[1m�[92m   Compiling�[0m flight-rules v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-rules)
2552:  �[1m�[92m   Compiling�[0m quick-error v1.2.3
2553:  �[1m�[92m   Compiling�[0m flight-hid-types v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hid-types)
...

2564:  �[1m�[92m   Compiling�[0m hidapi v2.6.5
2565:  �[1m�[92m   Compiling�[0m rand_chacha v0.9.0
2566:  �[1m�[92m   Compiling�[0m rand_xorshift v0.4.0
2567:  �[1m�[92m   Compiling�[0m rand v0.9.2
2568:  �[1m�[92m   Compiling�[0m bitflags v2.11.0
2569:  �[1m�[92m   Compiling�[0m unarray v0.1.4
2570:  �[1m�[92m   Compiling�[0m similar v2.7.0
2571:  �[1m�[92m   Compiling�[0m flight-hid v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hid)
2572:  �[1m�[92m   Compiling�[0m proptest v1.10.0
2573:  �[1m�[92m   Compiling�[0m insta v1.46.3
2574:  �[1m�[92m    Finished�[0m `test` profile [unoptimized + debuginfo] target(s) in 43.52s
2575:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_hid-792612c870e3f2a7.exe)
2576:  running 2 tests
2577:  test fd_safety_tests::clippy_config::test_fd_usage_examples ... ok
2578:  test fd_safety_tests::windows_tests::test_typed_handle_usage ... ok
2579:  test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 200 filtered out; finished in 0.00s
2580:  �[1m�[92m     Running�[0m tests\integration.rs (target\debug\deps\integration-ceeb865f425a7849.exe)
2581:  running 0 tests
2582:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 14 filtered out; finished in 0.00s
2583:  �[1m�[92m     Running�[0m tests\proptest_axis_calibration.rs (target\debug\deps\proptest_axis_calibration-d622df6fe5b9260f.exe)
2584:  �[1m�[92m     Running�[0m tests\snapshots.rs (target\debug\deps\snapshots-0e50c6c6cba33881.exe)
2585:  running 0 tests
2586:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 13 filtered out; finished in 0.00s
2587:  running 0 tests
2588:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 5 filtered out; finished in 0.00s
2589:  �[1m�[92m   Compiling�[0m windows-sys v0.61.2
...

2708:  �[1m�[92m   Compiling�[0m ciborium v0.2.2
2709:  �[1m�[92m   Compiling�[0m matchers v0.2.0
2710:  �[1m�[92m   Compiling�[0m tinytemplate v1.2.1
2711:  �[1m�[92m   Compiling�[0m thread_local v1.1.9
2712:  �[1m�[92m   Compiling�[0m oorandom v11.1.5
2713:  �[1m�[92m   Compiling�[0m anes v0.1.6
2714:  �[1m�[92m   Compiling�[0m proptest v1.10.0
2715:  �[1m�[92m   Compiling�[0m criterion v0.8.2
2716:  �[1m�[92m   Compiling�[0m tracing-subscriber v0.3.22
2717:  �[1m�[92m   Compiling�[0m tokio-test v0.4.5
2718:  �[1m�[92m    Finished�[0m `test` profile [unoptimized + debuginfo] target(s) in 1m 15s
2719:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_ipc-74ce1c29e103cca3.exe)
2720:  running 2 tests
2721:  test fd_safety_tests::fd_usage_examples::test_ipc_fd_usage_examples ... ok
2722:  test fd_safety_tests::windows_tests::test_typed_handle_usage_ipc ... ok
2723:  test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 171 filtered out; finished in 0.00s
2724:  �[1m�[92m     Running�[0m tests\grpc_tests.rs (target\debug\deps\grpc_tests-266f830c155c7b5c.exe)
2725:  running 0 tests
2726:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 21 filtered out; finished in 0.00s
2727:  �[1m�[92m     Running�[0m tests\ipc_fuzz_tests.rs (target\debug\deps\ipc_fuzz_tests-ecd20f41a7f303f9.exe)
2728:  running 0 tests
2729:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 5 filtered out; finished in 0.00s
2730:  �[1m�[92m     Running�[0m tests\proto_tests.rs (target\debug\deps\proto_tests-63614f4c2286312e.exe)
2731:  running 0 tests
2732:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 25 filtered out; finished in 0.00s
2733:  �[1m�[92m   Compiling�[0m windows-link v0.2.1
...

2736:  �[1m�[92m   Compiling�[0m serde v1.0.228
2737:  �[1m�[92m   Compiling�[0m windows-sys v0.61.2
2738:  �[1m�[92m   Compiling�[0m cc v1.2.56
2739:  �[1m�[92m   Compiling�[0m pin-project-lite v0.2.17
2740:  �[1m�[92m   Compiling�[0m serde_core v1.0.228
2741:  �[1m�[92m   Compiling�[0m num-traits v0.2.19
2742:  �[1m�[92m   Compiling�[0m once_cell v1.21.3
2743:  �[1m�[92m   Compiling�[0m memchr v2.8.0
2744:  �[1m�[92m   Compiling�[0m bytes v1.11.1
2745:  �[1m�[92m   Compiling�[0m itoa v1.0.17
2746:  �[1m�[92m   Compiling�[0m tracing v0.1.44
2747:  �[1m�[92m   Compiling�[0m windows_x86_64_msvc v0.53.1
2748:  �[1m�[92m   Compiling�[0m windows-targets v0.53.5
2749:  �[1m�[92m   Compiling�[0m tracing-core v0.1.36
2750:  �[1m�[92m   Compiling�[0m windows-sys v0.60.2
2751:  �[1m�[92m   Compiling�[0m thiserror v2.0.18
2752:  �[1m�[92m   Compiling�[0m stable_deref_trait v1.2.1
...

2868:  �[1m�[92m   Compiling�[0m icu_normalizer_data v2.1.1
2869:  �[1m�[92m   Compiling�[0m icu_properties_data v2.1.2
2870:  �[1m�[92m   Compiling�[0m flight-simconnect-sys v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-simconnect-sys)
2871:  �[1m�[92m   Compiling�[0m ryu v1.0.23
2872:  �[1m�[92m   Compiling�[0m untrusted v0.9.0
2873:  �[1m�[92m   Compiling�[0m icu_properties v2.1.2
2874:  �[1m�[92m   Compiling�[0m icu_normalizer v2.1.1
2875:  �[1m�[92m   Compiling�[0m tonic-prost-build v0.14.5
2876:  �[1m�[92m   Compiling�[0m http-body-util v0.1.3
2877:  �[1m�[92m   Compiling�[0m subtle v2.6.1
2878:  �[1m�[92m   Compiling�[0m flight-ipc v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-ipc)
2879:  �[1m�[92m   Compiling�[0m idna_adapter v1.2.1
2880:  �[1m�[92m   Compiling�[0m serde_urlencoded v0.7.1
2881:  �[1m�[92m   Compiling�[0m axum-core v0.5.6
2882:  �[1m�[92m   Compiling�[0m num-integer v0.1.46
2883:  �[1m�[92m   Compiling�[0m serde_path_to_error v0.1.20
2884:  �[1m�[92m   Compiling�[0m utf8_iter v1.0.4
...

2960:  �[1m�[92m   Compiling�[0m flight-hotas-thrustmaster v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hotas-thrustmaster)
2961:  �[1m�[92m   Compiling�[0m matchers v0.2.0
2962:  �[1m�[92m   Compiling�[0m thread_local v1.1.9
2963:  �[1m�[92m   Compiling�[0m reserve-port v2.3.0
2964:  �[1m�[92m   Compiling�[0m bytesize v2.3.1
2965:  �[1m�[92m   Compiling�[0m unsafe-libyaml v0.2.11
2966:  �[1m�[92m   Compiling�[0m axum-test v18.7.0
2967:  �[1m�[92m   Compiling�[0m serde_yaml_ng v0.10.0
2968:  �[1m�[92m   Compiling�[0m tokio-test v0.4.5
2969:  �[1m�[92m   Compiling�[0m flight-service v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-service)
2970:  �[1m�[92m    Finished�[0m `test` profile [unoptimized + debuginfo] target(s) in 3m 15s
2971:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_service-4ab2f4b8e4e41e8c.exe)
2972:  running 2 tests
2973:  test fd_safety_tests::fd_usage_examples::test_service_fd_usage_examples ... ok
2974:  test fd_safety_tests::windows_tests::test_service_system_handle_safety ... ok
2975:  test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 408 filtered out; finished in 0.00s
2976:  �[1m�[92m     Running�[0m unittests src\main.rs (target\debug\deps\flightd-f11122a588484984.exe)
2977:  running 0 tests
2978:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
2979:  �[1m�[92m     Running�[0m tests\service_integration.rs (target\debug\deps\service_integration-3c0df996be52184c.exe)
2980:  running 0 tests
2981:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 9 filtered out; finished in 0.00s
2982:  �[1m�[92m     Running�[0m tests\service_integration_tests.rs (target\debug\deps\service_integration_tests-c9478996da6b3000.exe)
2983:  running 0 tests
2984:  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 11 filtered out; finished in 0.00s
2985:  ##[group]Run echo "🔍 Verifying critical patterns are fixed..."
...

3004:  �[36;1mfi�[0m
3005:  �[36;1m�[0m
3006:  �[36;1m# Check for criterion::black_box usage�[0m
3007:  �[36;1mif git grep -n "criterion::black_box" -- 'crates/' 'benches/'; then�[0m
3008:  �[36;1m  echo "❌ Found criterion::black_box - should be std::hint::black_box"�[0m
3009:  �[36;1m  exit 1�[0m
3010:  �[36;1mfi�[0m
3011:  �[36;1m�[0m
3012:  �[36;1mecho "✅ All critical patterns verified"�[0m
3013:  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
3014:  env:
3015:  CARGO_TERM_COLOR: always
3016:  RUST_BACKTRACE: 1
3017:  CARGO_HOME: C:\Users\runneradmin\.cargo
3018:  CARGO_INCREMENTAL: 0
3019:  CACHE_ON_FAILURE: false
3020:  ##[endgroup]
3021:  🔍 Verifying critical patterns are fixed...
3022:  ✅ All critical patterns verified
3023:  ##[group]Run cargo test --all-features --workspace --lib --tests --exclude flight-hub-examples
3024:  �[36;1mcargo test --all-features --workspace --lib --tests --exclude flight-hub-examples�[0m
3025:  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
3026:  env:
3027:  CARGO_TERM_COLOR: always
3028:  RUST_BACKTRACE: 1
3029:  CARGO_HOME: C:\Users\runneradmin\.cargo
3030:  CARGO_INCREMENTAL: 0
3031:  CACHE_ON_FAILURE: false
3032:  ##[endgroup]
...

3165:  �[1m�[92m   Compiling�[0m flight-hotas-virpil v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hotas-virpil)
3166:  �[1m�[92m   Compiling�[0m flight-hotas-ch v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hotas-ch)
3167:  �[1m�[92m   Compiling�[0m flight-hotas-honeycomb v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hotas-honeycomb)
3168:  �[1m�[92m   Compiling�[0m flight-hotas-vpforce v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hotas-vpforce)
3169:  �[1m�[92m   Compiling�[0m flight-hotas-saitek v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hotas-saitek)
3170:  �[1m�[92m   Compiling�[0m flight-hotas-brunner v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-hotas-brunner)
3171:  �[1m�[92m   Compiling�[0m crossbeam-utils v0.8.21
3172:  �[1m�[92m   Compiling�[0m flight-integration-tests v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-integration-tests)
3173:  �[1m�[92m   Compiling�[0m num-integer v0.1.46
3174:  �[1m�[92m   Compiling�[0m crossbeam-epoch v0.9.18
3175:  �[1m�[92m   Compiling�[0m crossbeam-deque v0.8.6
3176:  �[1m�[92m   Compiling�[0m num-bigint v0.4.6
3177:  �[1m�[92m   Compiling�[0m crossbeam-queue v0.3.12
3178:  �[1m�[92m   Compiling�[0m crossbeam-channel v0.5.15
3179:  �[1m�[92m   Compiling�[0m wait-timeout v0.2.1
3180:  �[1m�[92m   Compiling�[0m quick-error v1.2.3
3181:  �[1m�[92m   Compiling�[0m num-rational v0.4.2
...

3294:  �[1m�[92m   Compiling�[0m flight-ksp v0.1.0 (D:\a\OpenFlight\OpenFlight\crates\flight-ksp)
3295:  �[1m�[93mwarning[E0133]�[0m�[1m�[97m: call to unsafe function `flight_axis::Node::step_soa` is unsafe and requires unsafe block�[0m
3296:  �[1m�[96m--> �[0mcrates\flight-axis\tests\detent_tests.rs:25:5
3297:  �[1m�[96m|�[0m
3298:  �[1m�[96m25�[0m �[1m�[96m|�[0m     node.step_soa(frame, state_ptr);
3299:  �[1m�[96m|�[0m     �[1m�[93m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^�[0m �[1m�[93mcall to unsafe function�[0m
3300:  �[1m�[96m|�[0m
3301:  �[1m�[96m= �[0m�[1m�[97mnote�[0m: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html>
3302:  �[1m�[96m= �[0m�[1m�[97mnote�[0m: consult the function's documentation for information on how to avoid undefined behavior
3303:  �[1m�[92mnote�[0m: an unsafe function restricts its caller, but its body is safe by default
3304:  �[1m�[96m--> �[0mcrates\flight-axis\tests\detent_tests.rs:23:1
3305:  �[1m�[96m|�[0m
3306:  �[1m�[96m23�[0m �[1m�[96m|�[0m unsafe fn process_frame_soa(node: &DetentNode, frame: &mut AxisFrame, state: &mut DetentState) {
3307:  �[1m�[96m|�[0m �[1m�[92m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^�[0m
3308:  �[1m�[96m= �[0m�[1m�[97mnote�[0m: `#[warn(unsafe_op_in_unsafe_fn)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
3309:  �[1m�[97mFor more information about this error, try `rustc --explain E0133`.�[0m
3310:  �[1m�[93mwarning�[0m: `flight-axis` (test "detent_tests") generated 1 warning (run `cargo fix --test "detent_tests" -p flight-axis` to apply 1 suggestion)
...

3450:  test tests::managed_block_is_idempotent ... ok
3451:  test tests::applies_profile_replaces_existing_managed_block ... ok
3452:  test tests::install_creates_dir_and_file ... ok
3453:  test tests::installs_with_backup ... ok
3454:  test tests::rc_mode_index_values ... ok
3455:  test tests::renders_all_rc_modes ... ok
3456:  test tests::renders_managed_block ... ok
3457:  test tests::steam_input_hint_is_nonempty ... ok
3458:  test tests::validates_empty_profile_name ... ok
3459:  test tests::validates_out_of_range_deadzone ... ok
3460:  test tests::validates_out_of_range_exponent ... ok
3461:  test tests::validates_out_of_range_scale ... ok
3462:  test tests::property_valid_deadzone_range_accepted ... ok
3463:  test tests::property_valid_exponent_range_accepted ... ok
3464:  test tests::property_valid_scale_range_accepted ... ok
3465:  test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
3466:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_ac7_protocol-b6e863ecbbb0259d.exe)
3467:  running 13 tests
3468:  test tests::aircraft_label_trims_whitespace ... ok
3469:  test tests::parses_valid_packet ... ok
3470:  test tests::defaults_schema_and_label ... ok
3471:  test tests::json_round_trip ... ok
3472:  test tests::property_bounded_altitude_valid ... ok
3473:  test tests::property_out_of_bounds_throttle_rejected ... ok
3474:  test tests::rejects_invalid_json ... ok
3475:  test tests::rejects_negative_speed ... ok
3476:  test tests::rejects_out_of_range_altitude ... ok
3477:  test tests::property_all_bounded_controls_valid ... ok
3478:  test tests::rejects_out_of_range_control_value ... ok
3479:  test tests::rejects_wrong_schema ... ok
3480:  test tests::property_pitch_control_is_bounded ... ok
3481:  test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
3482:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_ac7_telemetry-15e129c5b63bef41.exe)
3483:  running 10 tests
3484:  test tests::adapter_initial_state_is_disconnected ... ok
3485:  test tests::metrics_registry_tracks_config ... ok
3486:  test tests::snapshot_control_inputs_mapped ... ok
3487:  test tests::snapshot_has_correct_sim_id ... ok
3488:  test tests::converts_packet_to_snapshot ... ok
3489:  test tests::snapshot_validity_flags_set_from_full_packet ... ok
3490:  test tests::snapshot_validity_partial_packet ... ok
3491:  test tests::start_stop_cycle ... ok
3492:  test tests::poll_updates_source_addr ... ok
3493:  test tests::udp_poll_receives_packet ... ok
3494:  test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
3495:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_adapter_common-7bfc7ec097d45099.exe)
3496:  running 19 tests
3497:  test metrics::tests::test_record_aircraft_change ... ok
3498:  test metrics::tests::test_record_update_tracks_samples ... ok
3499:  test reconnect_backoff::tests::test_exponential_growth ... ok
3500:  test reconnect_backoff::tests::test_first_delay_equals_initial ... ok
3501:  test reconnect_backoff::tests::test_jitter_stays_within_bounds ... ok
3502:  test reconnect_backoff::tests::test_jitter_zero_means_no_jitter ... ok
3503:  test reconnect_backoff::tests::test_max_delay_cap ... ok
3504:  test reconnect_backoff::tests::test_reset_restarts_sequence ... ok
3505:  test reconnection::tests::test_backoff_progression ... ok
3506:  test reconnection::tests::test_should_retry ... ok
3507:  test tests::adapter_error_display_variants ... ok
3508:  test tests::adapter_metrics_summary_format ... ok
3509:  test tests::adapter_metrics_total_updates_increment ... ok
3510:  test tests::adapter_state_all_variants_debug ... ok
3511:  test tests::adapter_state_equality ... ok
3512:  test tests::reconnection_strategy_initial_backoff_on_first_attempt ... ok
3513:  test tests::reconnection_strategy_max_backoff_caps ... ok
3514:  test reconnect_backoff::tests::test_invalid_jitter_panics - should panic ... ok
3515:  test reconnect_backoff::tests::test_invalid_multiplier_panics - should panic ... ok
3516:  test result: ok. 19 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
3517:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_aerofly-e63951766d3fdf31.exe)
3518:  running 36 tests
3519:  test tests::adapter_custom_port ... ok
3520:  test tests::adapter_default_port ... ok
3521:  test tests::adapter_no_telemetry_initially ... ok
3522:  test tests::adapter_process_datagram_updates_last ... ok
3523:  test tests::adapter_process_invalid_datagram_returns_error ... ok
3524:  test tests::adapter_process_json_updates_last ... ok
3525:  test tests::adapter_process_text_updates_last ... ok
3526:  test tests::aircraft_type_case_insensitive ... ok
3527:  test tests::aircraft_type_from_name ... ok
3528:  test tests::airspeed_conversion_knots_to_ms ... ok
3529:  test tests::altitude_conversion_ft_to_m ... ok
3530:  test tests::attitude_conversion_deg_to_rad ... ok
3531:  test tests::bad_magic_returns_error ... ok
3532:  test tests::empty_frame_returns_error ... ok
3533:  test tests::flaps_ratio_clamped_below_zero ... ok
3534:  test tests::frame_too_short_returns_error ... ok
3535:  test tests::gear_down_byte_nonzero ... ok
3536:  test tests::gear_up_byte_zero ... ok
3537:  test tests::invalid_json_returns_error ... ok
3538:  test tests::json_vspeed_defaults_to_zero_when_absent ... ok
3539:  test tests::parse_text_all_fields ... ok
3540:  test tests::parse_text_gear_state_boundary ... ok
3541:  test tests::parse_text_empty_returns_error ... ok
3542:  test tests::parse_text_invalid_numbers_default_to_zero ... ok
3543:  test tests::parse_text_negative_altitude ... ok
3544:  test tests::parse_text_partial_uses_defaults ... ok
3545:  test tests::parse_text_throttle_clamped ... ok
3546:  test tests::parse_text_unknown_keys_ignored ... ok
3547:  test tests::parse_text_whitespace_tolerance ... ok
3548:  test tests::parse_valid_binary_frame ... ok
3549:  test tests::parse_valid_json ... ok
3550:  test tests::telemetry_default_values ... ok
3551:  test tests::telemetry_serde_round_trip ... ok
3552:  test tests::throttle_clamped_above_one ... ok
3553:  test tests::vspeed_conversion_fpm_to_ms ... ok
3554:  test tests::zero_altitude_conversion ... ok
3555:  test result: ok. 36 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
3556:  �[1m�[92m     Running�[0m tests\integration_tests.rs (target\debug\deps\integration_tests-aaf1054325880608.exe)
3557:  running 10 tests
3558:  test attitude_roll_pitch_heading_in_correct_units ... ok
3559:  test airspeed_and_vertical_state_fields_present ... ok
3560:  test adapter_processes_binary_and_json_paths ... ok
3561:  test adapter_json_round_trip_preserves_all_fields ... ok
3562:  test coordinates_altitude_and_heading_decoded_correctly ... ok
3563:  test text_format_parsed_and_all_three_paths_work ... ok
3564:  test missing_fields_in_json_returns_error_gracefully ... ok
3565:  test malformed_json_returns_error_not_panic ... ok
3566:  test unit_conversion_helpers_are_consistent ... ok
3567:  test valid_json_telemetry_packet_parsed ... ok
3568:  test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
3569:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_axis-64a16df3df3ffffa.exe)
...

3576:  test accumulator::tests::test_reset_to_zero ... ok
3577:  test accumulator::tests::test_scale_factor ... ok
3578:  test accumulator::tests::test_wrap_negative ... ok
3579:  test accumulator::tests::test_wrap_positive ... ok
3580:  test blackbox::tests::test_annotator_creation ... ok
3581:  test blackbox::tests::test_buffer_flush ... ok
3582:  test blackbox::tests::test_conflict_annotation ... ok
3583:  test blackbox::tests::test_conflict_data_conversion ... ok
3584:  test blackbox::tests::test_disabled_annotation ... ok
3585:  test blackbox::tests::test_disabled_annotator ... ok
3586:  test blackbox::tests::test_resolution_annotation ... ok
3587:  test buttons::tests::test_axis_offset_action ... ok
3588:  test buttons::tests::test_axis_set_action ... ok
3589:  test buttons::tests::test_chord_partial_press_no_fire ... ok
3590:  test buttons::tests::test_chord_requires_all_buttons ... ok
3591:  test buttons::tests::test_chord_too_many_buttons_error ... ok
3592:  test buttons::tests::test_clear_removes_all_macros ... ok
3593:  test buttons::tests::test_duplicate_button_error ... ok
3594:  test buttons::tests::test_empty_chord_error ... ok
3595:  test buttons::tests::test_hold_fires_after_threshold ... ok
...

3617:  test calibration::tests::proptest_clamp_extremes ... ok
3618:  test calibration::tests::test_calbank_insert_and_get ... ok
3619:  test calibration::tests::test_calbank_unknown_axis_uses_default ... ok
3620:  test calibration::tests::test_normalize_8bit ... ok
3621:  test calibration::tests::test_normalize_above_deadband ... ok
3622:  test calibration::tests::test_normalize_center_is_zero ... ok
3623:  test calibration::tests::test_normalize_clamped_above_max ... ok
3624:  test calibration::tests::test_normalize_clamped_below_min ... ok
3625:  test calibration::tests::test_normalize_deadband_near_center ... ok
3626:  test calibration::tests::test_normalize_max_is_one ... ok
3627:  test calibration::tests::test_normalize_midpoint_above_center ... ok
3628:  test calibration::tests::test_normalize_midpoint_below_center ... ok
3629:  test calibration::tests::test_normalize_min_equals_max ... ok
3630:  test calibration::tests::test_normalize_min_is_neg_one ... ok
3631:  test calibration::tests::test_normalize_virpil_14bit ... ok
3632:  test calibration_wizard::tests::center_detection_noisy_fails ... ok
3633:  test buttons::tests::proptest_output_count_never_exceeds_8 ... ok
3634:  test calibration_wizard::tests::center_detection_stable_succeeds ... ok
3635:  test calibration_wizard::tests::complete_produces_result ... ok
3636:  test calibration_wizard::tests::deadzone_recommends_value ... ok
3637:  test calibration_wizard::tests::initial_state_is_not_started ... ok
3638:  test calibration_wizard::tests::progress_increases_through_steps ... ok
3639:  test calibration_wizard::tests::reset_returns_to_not_started ... ok
3640:  test calibration_wizard::tests::samples_ignored_in_terminal_states ... ok
3641:  test calibration_wizard::tests::start_transitions_to_center_detection ... ok
3642:  test calibration_wizard::tests::sweep_detects_full_range ... ok
3643:  test calibration_wizard::tests::sweep_insufficient_range_fails ... ok
3644:  test calibration_wizard::tests::timeout_fails_center_detection ... ok
3645:  test calibration_wizard::tests::verification_fails_non_monotonic ... ok
3646:  test calibration_wizard::tests::verification_passes_linear ... ok
...

3735:  test curve::tests::test_expo_negative_increases_center_sensitivity ... ok
3736:  test curve::tests::test_expo_one_input_maps_to_one ... ok
3737:  test curve::tests::test_expo_positive_reduces_center_sensitivity ... ok
3738:  test curve::tests::test_expo_zero_input_maps_to_zero ... ok
3739:  test curve::tests::test_expo_zero_is_linear ... ok
3740:  test curve::tests::test_is_monotone_identity ... ok
3741:  test curve::tests::prop_output_always_in_range ... ok
3742:  test curve::tests::test_linear_identity_constructor ... ok
3743:  test curve::tests::test_linear_identity_evaluates_x ... ok
3744:  test curve::tests::test_linear_identity_one ... ok
3745:  test curve::tests::test_linear_identity_zero ... ok
3746:  test curve::tests::test_linear_interpolation_midpoint ... ok
3747:  test curve::tests::test_monotone_cubic_identity ... ok
3748:  test curve::tests::test_standard_deadzone_expo_curve ... ok
3749:  test curve::tests::test_monotone_cubic_preserves_monotone ... ok
3750:  test curve::tests::test_too_few_points_error ... ok
3751:  test curve::tests::test_unsorted_points_error ... ok
3752:  test deadzone::tests::prop_antisymmetric ... ok
...

3758:  test deadzone::tests::test_asymmetric_negative_deadzone ... ok
3759:  test deadzone::tests::test_asymmetric_positive_deadzone ... ok
3760:  test deadzone::tests::test_asymmetric_symmetric_matches_center_only ... ok
3761:  test deadzone::tests::test_asymmetric_zero_positive_passes_positive ... ok
3762:  test deadzone::tests::test_bank_apply ... ok
3763:  test deadzone::tests::test_bank_set_config ... ok
3764:  test deadzone::tests::test_center_deadzone_full_deflection ... ok
3765:  test deadzone::tests::test_center_deadzone_negative ... ok
3766:  test deadzone::tests::test_center_deadzone_outside_zone ... ok
3767:  test deadzone::tests::test_center_deadzone_within_zone ... ok
3768:  test deadzone::tests::test_clamp_above_one ... ok
3769:  test deadzone::tests::test_clamp_below_neg_one ... ok
3770:  test deadzone::tests::test_combined_center_and_edge ... ok
3771:  test deadzone::tests::test_edge_deadzone_below ... ok
3772:  test deadzone::tests::test_edge_deadzone_saturation ... ok
3773:  test deadzone::tests::test_invalid_center_error ... ok
3774:  test deadzone::tests::test_overlap_error ... ok
3775:  test deadzone::tests::test_zero_deadzone_passthrough ... ok
...

3897:  test invert::tests::test_invert_disabled_passthrough ... ok
3898:  test invert::tests::test_invert_enabled_negates ... ok
3899:  test invert::tests::test_invert_negative_one ... ok
3900:  test invert::tests::test_invert_positive_one ... ok
3901:  test invert::tests::test_invert_toggle ... ok
3902:  test invert::tests::test_invert_zero_unchanged ... ok
3903:  test lag_compensator::tests::first_sample_passes_through ... ok
3904:  test lag_compensator::tests::max_prediction_clamped ... ok
3905:  test lag_compensator::tests::moving_axis_is_predicted_ahead ... ok
3906:  test lag_compensator::tests::nan_passes_through_unchanged ... ok
3907:  test lag_compensator::tests::negative_movement_predicts_backward ... ok
3908:  test lag_compensator::tests::output_is_clamped_to_valid_range ... ok
3909:  test lag_compensator::tests::reset_clears_initialized ... ok
3910:  test lag_compensator::tests::static_axis_unchanged ... ok
3911:  test lag_compensator::tests::zero_dt_uses_last_dt ... ok
3912:  test mixer::tests::add_input_beyond_max_fails ... ok
3913:  test mixer::tests::add_input_increments_count ... ok
...

3989:  test pid::tests::test_pid_bank_reset_not_needed ... ok
3990:  test pid::tests::test_pid_bank_update_known_axis ... ok
3991:  test pid::tests::test_pid_bank_update_unknown_axis ... ok
3992:  test pid::tests::test_pid_converges_step_response ... ok
3993:  test pid::tests::test_pid_derivative_on_step ... ok
3994:  test pid::tests::test_pid_derivative_zero_first_tick ... ok
3995:  test pid::tests::test_pid_integral_accumulates ... ok
3996:  test pid::tests::test_pid_integral_windup_limited ... ok
3997:  test pid::tests::test_pid_output_clamped_to_1 ... ok
3998:  test pid::tests::test_pid_output_clamped_to_neg1 ... ok
3999:  test pid::tests::test_pid_proportional_only ... ok
4000:  test pid::tests::test_pid_reset_clears_state ... ok
4001:  test pid::tests::test_pid_set_integral_clamped ... ok
4002:  test pid::tests::test_pid_setpoint_above_pv ... ok
4003:  test pid::tests::test_pid_setpoint_below_pv ... ok
4004:  test pid::tests::test_pid_zero_error ... ok
4005:  test pipeline::tests::test_alignment ... ok
...

4009:  test pipeline::tests::test_curve_stage_expo ... ok
4010:  test pipeline::tests::test_curve_stage_linear ... ok
4011:  test pipeline::tests::test_deadzone_stage_center ... ok
4012:  test pipeline::tests::test_deadzone_stage_full_deflection ... ok
4013:  test pipeline::tests::test_deadzone_stage_negative ... ok
4014:  test pipeline::tests::test_deadzone_stage_rescale ... ok
4015:  test pipeline::tests::test_default_pipeline_is_empty ... ok
4016:  test pipeline::tests::test_diagnostics_captures_per_stage_io ... ok
4017:  test pipeline::tests::test_diagnostics_respects_bypass ... ok
4018:  test pipeline::tests::test_empty_pipeline_passthrough ... ok
4019:  test pipeline::tests::test_enable_stage_after_bypass ... ok
4020:  test pipeline::tests::test_insert_stage_at_beginning ... ok
4021:  test pipeline::tests::test_insert_stage_at_end ... ok
4022:  test pipeline::tests::test_pipeline_multi_stage ... ok
4023:  test pipeline::tests::test_pipeline_state_creation ... ok
4024:  test pid::tests::proptest_zero_error_zero_output ... ok
4025:  test pipeline::tests::test_remove_stage_out_of_bounds ... ok
...

4105:  test recording::tests::test_playback_is_finished_at_end ... ok
4106:  test recording::tests::test_playback_looping_wraps_around ... ok
4107:  test recording::tests::test_playback_rewind ... ok
4108:  test recording::tests::test_record_multiple_samples ... ok
4109:  test rate_limit::tests::proptest_rate_limited_no_overshoot ... ok
4110:  test recording::tests::test_record_single_sample ... ok
4111:  test recording::tests::test_recording_duration ... ok
4112:  test recording::tests::test_recording_empty_by_default ... ok
4113:  test recording::tests::test_samples_in_range ... ok
4114:  test scale::tests::test_bank_apply ... ok
4115:  test scale::tests::test_bank_set_scale ... ok
4116:  test scale::tests::test_scale_clamp_max ... ok
4117:  test scale::tests::test_scale_clamp_min ... ok
4118:  test scale::tests::test_scale_default_passthrough ... ok
4119:  test scale::tests::test_scale_factor_half ... ok
4120:  test scale::tests::test_scale_invalid_range_error ... ok
4121:  test scale::tests::test_scale_nan_factor_error ... ok
4122:  test scale::tests::test_scale_negative_factor ... ok
...

4241:  test stages::tests::very_large_values_handled ... ok
4242:  test throttle_zone::tests::prop_output_always_in_range ... ok
4243:  test throttle_zone::tests::prop_event_count_never_exceeds_4 ... ok
4244:  test throttle_zone::tests::test_afterburner_zone_event ... ok
4245:  test throttle_zone::tests::test_builder_pattern ... ok
4246:  test throttle_zone::tests::test_combined_cut_and_milpower ... ok
4247:  test throttle_zone::tests::test_cut_zone_above_threshold ... ok
4248:  test throttle_zone::tests::test_cut_zone_at_threshold ... ok
4249:  test throttle_zone::tests::test_cut_zone_below_threshold ... ok
4250:  test throttle_zone::tests::test_max_zone_below_threshold ... ok
4251:  test throttle_zone::tests::test_max_zone_saturation ... ok
4252:  test throttle_zone::tests::test_milpower_zone_event_on_entry ... ok
4253:  test throttle_zone::tests::test_milpower_zone_event_on_exit ... ok
4254:  test throttle_zone::tests::test_no_zones_passthrough ... ok
4255:  test throttle_zone::tests::test_process_clamped_input_above_one ... ok
4256:  test throttle_zone::tests::test_validate_cut_above_max_error ... ok
4257:  test throttle_zone::tests::test_validate_invalid_cut_threshold ... ok
...

4282:  test trim::tests::test_trimbank_apply_unknown_axis ... ok
4283:  test trim::tests::test_trimbank_get_or_insert ... ok
4284:  test trim::tests::proptest_apply_output_bounded ... ok
4285:  test trim::tests::test_trimbank_reset_all ... ok
4286:  test trim::tests::proptest_decrement_bounded ... ok
4287:  test velocity::tests::test_velocity_negative_movement ... ok
4288:  test velocity::tests::test_velocity_no_smoothing ... ok
4289:  test velocity::tests::test_velocity_positive_movement ... ok
4290:  test velocity::tests::test_velocity_reset ... ok
4291:  test velocity::tests::test_velocity_smoothing ... ok
4292:  test velocity::tests::test_velocity_units ... ok
4293:  test velocity::tests::test_velocity_invalid_alpha_panics - should panic ... ok
4294:  test velocity::tests::test_velocity_zero_at_rest ... ok
4295:  test velocity::tests::test_velocity_invalid_period_panics - should panic ... ok
4296:  test trim::tests::proptest_increment_bounded ... ok
4297:  test result: ok. 726 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.56s
4298:  �[1m�[92m     Running�[0m tests\detent_integration.rs (target\debug\deps\detent_integration-ed36fb410ff34c8f.exe)
4299:  running 8 tests
4300:  test test_detent_builder_api ... ok
4301:  test test_detent_hysteresis_with_slew ... ok
4302:  test test_detent_events_in_pipeline ... ok
4303:  test test_detent_in_complete_pipeline ... ok
4304:  test test_detent_output_snapping ... ok
4305:  test test_detent_with_curve_interaction ... ok
4306:  test test_multiple_detent_transitions ... ok
4307:  test test_detent_performance_in_pipeline ... ok
4308:  test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.62s
4309:  �[1m�[92m     Running�[0m tests\detent_tests.rs (target\debug\deps\detent_tests-097e8f83c9ceb2ac.exe)
4310:  running 13 tests
4311:  test test_detent_role_names ... ok
4312:  test test_detent_zone_clamping ... ok
4313:  test test_detent_zone_containment ... ok
4314:  test test_detent_zone_creation ... ok
4315:  test test_hysteresis_prevents_flapping ... ok
4316:  test test_multiple_detents_no_overlap ... ok
4317:  test test_no_snap_detent ... ok
4318:  test test_node_trait_implementation ... ok
4319:  test test_single_detent_entry_exit ... ok
4320:  test test_sweep_single_transitions ... ok
4321:  test test_zone_sorting ... ok
4322:  test test_hysteresis_stability ... ok
4323:  test test_deterministic_detent_behavior ... ok
4324:  test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
4325:  �[1m�[92m     Running�[0m tests\filter_tests.rs (target\debug\deps\filter_tests-29d4f6e98fca602b.exe)
4326:  running 10 tests
4327:  test test_filter_alpha_one_is_identity ... ok
4328:  test test_filter_alpha_zero_holds_initial_value ... ok
4329:  test test_b104_spike_rejection_ignores_single_transient ... ok
4330:  test test_filter_converges_toward_constant_input ... ok
4331:  test test_filter_ema_smoothing_on_step_input ... ok
4332:  test test_filter_first_sample_passthrough ... ok
4333:  test test_filter_inf_does_not_panic ... ok
4334:  test test_filter_nan_does_not_panic ... ok
4335:  test test_filter_output_bounded_for_valid_inputs ... ok
4336:  test filter_output_in_range ... ok
4337:  test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
4338:  �[1m�[92m     Running�[0m tests\integration_tests.rs (target\debug\deps\integration_tests-318cfa7058261877.exe)
4339:  running 26 tests
4340:  test test_allocation_guard ... ok
4341:  test test_axis_engine_creation ... ok
4342:  test test_axis_engine_process_without_pipeline ... ok
4343:  test test_atomic_pipeline_swap_with_ack ... ok
4344:  test test_axis_engine_with_config ... ok
4345:  test test_axis_frame_creation ... ok
4346:  test test_axis_frame_derivative_calculation ... ok
4347:  test test_compile_failure_safety ... ok
4348:  test test_curve_node_exponential ... ok
...

4351:  test test_deadzone_node_symmetric ... ok
4352:  test test_deterministic_processing ... ok
4353:  test test_end_to_end_pipeline_processing ... ok
4354:  test test_node_state_sizes ... ok
4355:  test test_performance_snapshot ... ok
4356:  test test_node_type_identification ... ok
4357:  test test_pipeline_builder ... ok
4358:  test test_pipeline_state_validation ... ok
4359:  test test_runtime_counters_averaging ... ok
4360:  test test_runtime_counters ... ok
4361:  test test_slew_node_rate_limiting ... ok
4362:  test test_zero_allocation_constraint_validation ... ok
4363:  test test_zero_allocation_guarantee ... ok
4364:  test test_processing_performance ... ok
4365:  test test_performance_under_load ... ok
4366:  test result: ok. 26 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.81s
4367:  �[1m�[92m     Running�[0m tests\mixer_tests.rs (target\debug\deps\mixer_tests-bb55e39fdf9e6753.exe)
...

4384:  test test_mixer_input_creation ... ok
4385:  test test_mixer_input_with_scale ... ok
4386:  test test_mixer_mathematical_properties ... ok
4387:  test test_mixer_node_creation ... ok
4388:  test test_mixer_node_creation_with_invalid_config ... ok
4389:  test test_mixer_node_trait_implementation ... ok
4390:  test test_mixer_process_inputs_basic ... ok
4391:  test test_mixer_process_inputs_no_clamp ... ok
4392:  test test_mixer_process_inputs_with_gain ... ok
4393:  test test_mixer_soa_step_processing ... ok
4394:  test test_mixer_state_initialization ... ok
4395:  test test_mixer_unit_handling_validation ... ok
4396:  test test_mixer_zero_allocation_constraint ... ok
4397:  test test_mixer_zero_allocation_integration ... ok
4398:  test test_mixer_performance_characteristics ... ok
4399:  test result: ok. 30 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
4400:  �[1m�[92m     Running�[0m tests\performance_validation.rs (target\debug\deps\performance_validation-cc0db11fb58b6cbc.exe)
4401:  running 4 tests
4402:  test test_atomic_swap_performance ... ok
4403:  test test_jitter_requirements ... ok
4404:  test test_rt_performance_requirements ... ok
4405:  test test_zero_allocation_validation ... ok
4406:  test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.59s
4407:  �[1m�[92m     Running�[0m tests\pipeline_composition_tests.rs (target\debug\deps\pipeline_composition_tests-a5ec6674c1d4cb4e.exe)
4408:  running 11 tests
4409:  test test_deadzone_curve_output_is_monotone_for_positive_inputs ... ok
4410:  test test_filter_smooths_step_after_deadzone ... ok
4411:  test test_max_positive_input_stays_bounded_through_deadzone_curve_slew ... ok
4412:  test test_nan_input_does_not_panic_in_full_pipeline ... ok
4413:  test test_neg_inf_does_not_panic_in_deadzone_pipeline ... ok
4414:  test test_positive_inf_does_not_panic_in_full_pipeline ... ok
4415:  test test_slew_limits_sudden_large_jump ... ok
4416:  test test_zero_input_stays_zero_through_deadzone_curve_slew ... ok
4417:  test deadzone_curve_is_monotone_for_positive_inputs ... ok
4418:  test deadzone_curve_output_in_range ... ok
4419:  test full_pipeline_output_in_range ... ok
4420:  test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
4421:  �[1m�[92m     Running�[0m tests\pipeline_integration.rs (target\debug\deps\pipeline_integration-1a833898a6f481b3.exe)
4422:  running 7 tests
4423:  test test_pipeline_center_no_processing ... ok
4424:  test test_pipeline_max_input_no_trim ... ok
4425:  test test_pipeline_max_input_max_trim_clamps ... ok
4426:  test test_pipeline_min_input_no_trim ... ok
4427:  test test_pipeline_output_always_bounded ... ok
4428:  test test_pipeline_rate_limit_slows_changes ... ok
4429:  test test_pipeline_smoothing_reduces_step_response ... ok
4430:  test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
4431:  �[1m�[92m     Running�[0m tests\proptest_invariants.rs (target\debug\deps\proptest_invariants-67cfe137d99bcb9f.exe)
4432:  running 14 tests
4433:  test clamp_never_exceeds_bounds ... ok
4434:  test deadzone_output_zero_within_zone ... ok
4435:  test expo_output_bounded ... ok
4436:  test expo_preserves_sign ... ok
4437:  test rt_deadzone_output_bounded ... ok
4438:  test rt_curve_expo_monotone ... ok
4439:  test rt_pipeline_output_finite ... ok
4440:  test pipeline_output_finite ... ok
4441:  test saturation_bipolar_bounds ... ok
4442:  test saturation_output_within_bounds ... ok
4443:  test slew_rate_unlimited_passthrough ... ok
4444:  test smoothing_ema_converges_to_constant ... ok
4445:  test slew_rate_delta_bounded ... ok
4446:  test smoothing_output_always_finite ... ok
4447:  test result: ok. 14 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
4448:  �[1m�[92m     Running�[0m tests\rt_coverage.rs (target\debug\deps\rt_coverage-b0bf42546861503a.exe)
...

4459:  test test_combined_deadzone_expo_zeroes_inside_zone ... ok
4460:  test test_curve_expo_zero_is_linear ... ok
4461:  test test_curve_expo_one_max_curvature ... ok
4462:  test test_curve_scurve_reduces_centre_gain ... ok
4463:  test test_deadzone_negative_boundary ... ok
4464:  test test_deadzone_value_at_exact_threshold ... ok
4465:  test test_deadzone_value_inside_is_zero ... ok
4466:  test test_range_clamp_at_limits ... ok
4467:  test test_deadzone_value_just_outside_is_nonzero ... ok
4468:  test test_split_bipolar_half_positive ... ok
4469:  test test_split_bipolar_negative_one ... ok
4470:  test test_split_bipolar_positive_one ... ok
4471:  test test_split_bipolar_zero ... ok
4472:  test prop_split_bipolar_sum_equals_abs ... ok
4473:  test prop_combine_differential_bounded ... ok
4474:  test result: ok. 24 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
4475:  �[1m�[92m     Running�[0m tests\rt_timing_test.rs (target\debug\deps\rt_timing_test-3d8c4cf99cfac491.exe)
4476:  running 2 tests
4477:  test axis_pipeline_p99_within_4ms_budget ... ok
4478:  test axis_pipeline_fits_in_rt_budget ... ok
4479:  test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.07s
4480:  �[1m�[92m     Running�[0m tests\snapshot_tests.rs (target\debug\deps\snapshot_tests-8a7bcb41bf8d3985.exe)
4481:  running 3 tests
4482:  test snapshot_curve_node_expo_0_4_outputs ... ok
4483:  test snapshot_deadzone_expo_pipeline_output_values ... ok
4484:  test snapshot_deadzone_expo_pipeline_metadata ... ok
4485:  test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.16s
4486:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_bdd_metrics-2f4bbbb43d341ee8.exe)
4487:  running 14 tests
4488:  test tests::coverage_percent_full_coverage ... ok
4489:  test tests::bdd_traceability_row_coverage_methods ... ok
4490:  test tests::coverage_percent_zero_denominator_returns_zero ... ok
4491:  test tests::bdd_scenario_ac_tags_filters_non_ac_tags ... ok
4492:  test tests::coverage_status_compute_all_branches ... ok
4493:  test tests::extract_crates_from_command_parses_p_flag ... ok
4494:  test tests::extract_crates_from_reference_cmd_prefix ... ok
4495:  test tests::extract_crates_from_reference_double_colon_notation ... ok
4496:  test tests::is_crate_name_candidate_valid_and_invalid ... ok
4497:  test tests::is_scenario_header_recognises_scenario_types ... ok
4498:  test tests::normalize_crate_name_strips_quotes_and_underscores ... ok
4499:  test tests::parse_tags_from_line_extracts_tags ... ok
4500:  test tests::with_workspace_crates_preserves_unmapped_row ... ok
4501:  test tests::with_workspace_crates_filters_non_workspace_rows ... ok
4502:  test result: ok. 14 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
4503:  �[1m�[92m     Running�[0m unittests src\lib.rs (target\debug\deps\flight_blackbox-98b7135a86926b25.exe)
...

4528:  test recorder::tests::iterator_exact_size ... ok
4529:  test recorder::tests::mixed_record_types_in_buffer ... ok
4530:  test export::tests::json_csv_agree_on_axis_count ... ok
4531:  test recorder::tests::new_recorder_is_empty ... ok
4532:  test recorder::tests::record_event_stores_correctly ... ok
4533:  test recorder::tests::large_overflow_preserves_newest ... ok
4534:  test recorder::tests::record_and_retrieve_axis ... ok
4535:  test recorder::tests::record_ffb_stores_correctly ... ok
4536:  test recorder::tests::record_telemetry_stores_correctly ... ok
4537:  test recorder::tests::ring_buffer_exact_capacity_fill ... ok
4538:  test recorder::tests::ring_buffer_overflow_drops_oldest ... ok
4539:  test recorder::tests::zero_alloc_on_hot_path ... ok
4540:  test recorder::tests::zero_capacity_clamped_to_one ... ok
4541:  test tests::blackbox_config_def...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants