diff --git a/crates/openlogi-agent/src/bin/mock_agent.rs b/crates/openlogi-agent/src/bin/mock_agent.rs index 679589096..81c4dbb72 100644 --- a/crates/openlogi-agent/src/bin/mock_agent.rs +++ b/crates/openlogi-agent/src/bin/mock_agent.rs @@ -429,10 +429,7 @@ fn standalone_light() -> StandaloneDevice { zones: false, }), driver_id: "litra".to_string(), - // Must stay `Some` until #571 is fixed: `registry_model_id` is - // `skip_serializing_if`, which truncates the bincode stream when it is - // `None` and makes the whole snapshot undecodable. `8c900` is also the - // real registry id for a Litra Glow, so the asset lookup resolves. + // `8c900` is the real registry id for a Litra Glow, so the asset lookup resolves. registry_model_id: Some("8c900".to_string()), } } diff --git a/crates/openlogi-core/src/device.rs b/crates/openlogi-core/src/device.rs index d12f592ad..68ef6de13 100644 --- a/crates/openlogi-core/src/device.rs +++ b/crates/openlogi-core/src/device.rs @@ -407,7 +407,7 @@ pub struct StandaloneDevice { /// /// This is deliberately appended: `StandaloneDevice` crosses the /// append-only GUI↔agent bincode wire format. - #[serde(default, skip_serializing_if = "Option::is_none")] + #[serde(default)] pub registry_model_id: Option, } diff --git a/crates/openlogi-ipc/src/ipc.rs b/crates/openlogi-ipc/src/ipc.rs index 391daf121..fdc218dbb 100644 --- a/crates/openlogi-ipc/src/ipc.rs +++ b/crates/openlogi-ipc/src/ipc.rs @@ -52,7 +52,8 @@ pub use succession::Identity; /// [`RingObservation`]). /// v22: DPI scalar values use the validated [`Dpi`] type end to end. /// v23: SmartShift writes carry one typed [`SmartShiftStatus`] value. -pub const PROTOCOL_VERSION: u32 = 23; +/// v24: `StandaloneDevice::registry_model_id` is always encoded (bincode fix). +pub const PROTOCOL_VERSION: u32 = 24; /// Environment variable through which the agent hands a supervised helper the /// run token it will serve, so the helper knows which agent it belongs to diff --git a/crates/openlogi-ipc/tests/wire_format.rs b/crates/openlogi-ipc/tests/wire_format.rs index 5c293843c..2b3eb2447 100644 --- a/crates/openlogi-ipc/tests/wire_format.rs +++ b/crates/openlogi-ipc/tests/wire_format.rs @@ -63,12 +63,31 @@ fn wire_bytes(value: &T) -> String { } #[track_caller] -fn assert_wire(value: &T, golden: &str) { +fn assert_wire(value: &T, golden: &str) +where + T: serde::Serialize + serde::de::DeserializeOwned + std::fmt::Debug, +{ + let hex = wire_bytes(value); assert_eq!( - wire_bytes(value), - golden, + hex, golden, "wire encoding changed — if intentional, bump PROTOCOL_VERSION and regenerate this golden" ); + let bytes = (0..hex.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).expect("valid hex")) + .collect::>(); + let decoded: T = bincode::DefaultOptions::new() + .deserialize(&bytes) + .expect("wire types deserialize"); + // Re-encode the decoded value and compare — this validates the round-trip + // without requiring `PartialEq` on every wire type (e.g. `AgentRequest` + // generated by tarpc, `WriteError`). For types that do implement + // `PartialEq`, this is equivalent to `decoded == value`. + let re_hex = wire_bytes(&decoded); + assert_eq!( + hex, re_hex, + "wire round-trip failed — re-encoded bytes differ" + ); } fn representative_smartshift_status() -> SmartShiftStatus { @@ -85,7 +104,7 @@ fn representative_smartshift_status() -> SmartShiftStatus { /// that makes that visible in the same diff. #[test] fn protocol_version_is_pinned() { - assert_eq!(PROTOCOL_VERSION, 23); + assert_eq!(PROTOCOL_VERSION, 24); } #[test] @@ -511,7 +530,7 @@ fn standalone_light_dtos_commands_and_errors() { legacy.registry_model_id = None; assert_wire( &legacy, - "fb6d04fb00c9fb43fffb02020d73657269616c3a676c6f772d310a4c6974726120476c6f7701044c6f67690106676c6f772d31000000000d010001010114fa010101fb8c0afb641964020000056c69747261", + "fb6d04fb00c9fb43fffb02020d73657269616c3a676c6f772d310a4c6974726120476c6f7701044c6f67690106676c6f772d31000000000d010001010114fa010101fb8c0afb641964020000056c6974726100", ); assert_wire(&capabilities, "010114fa010101fb8c0afb641964020000"); assert_wire(&brightness, "14fa0101");