From 7326bb926257012c9744d875d8e7630cbba6de48 Mon Sep 17 00:00:00 2001 From: archipelago Date: Wed, 29 Jul 2026 03:34:02 -0400 Subject: [PATCH] fix(mesh): unpinned preferred path must stay an auto-detect candidate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Post-merge regression from combining two individually-correct changes: main's 2026-07-23 fix makes open_preferred_path bail WITHOUT touching the port when no device_kind is pinned, while the hw-config branch's skip_path dedup excludes the preferred path from the auto-detect fallback on the assumption it was already probed this cycle. Together, on a single-radio node with no pin (the common fleet state), the only candidate was never probed at all and the mesh never came up — hit live on archi-dev-box right after deploying merged main. Fix: when device_kind is None, skip open_preferred_path entirely and go straight to auto_detect_and_open with skip_path=None. The pinned path keeps the existing probe-then-skip fallback. Verified live on archi-dev-box: radio auto-detected, Reticulum daemon ready, 5 persisted peers loaded. Mesh tests 116 passed / 0 failed. Co-Authored-By: Claude Fable 5 --- core/archipelago/src/mesh/listener/session.rs | 67 ++++++++++++------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/core/archipelago/src/mesh/listener/session.rs b/core/archipelago/src/mesh/listener/session.rs index 140e39e1..c6fb1de7 100644 --- a/core/archipelago/src/mesh/listener/session.rs +++ b/core/archipelago/src/mesh/listener/session.rs @@ -1012,31 +1012,48 @@ pub(super) async fn run_mesh_session( ) .await } else if let Some(path) = preferred_path { - match open_preferred_path( - path, - data_dir, - our_ed_pubkey_hex, - our_x25519_pubkey_hex, - device_kind, - Some(&desired_advert_name), - ) - .await - { - Ok((dev, info)) => Ok((path.to_string(), dev, info)), - Err(e) => { - warn!( - "Preferred path {} probe failed: {} — trying auto-detect", - path, e - ); - auto_detect_and_open( - data_dir, - our_ed_pubkey_hex, - our_x25519_pubkey_hex, - device_kind, - Some(path), - Some(&desired_advert_name), - ) - .await + if device_kind.is_none() { + // Unpinned: open_preferred_path bails without ever touching + // the port, so the preferred path has NOT been probed this + // cycle — auto-detect must keep it as a candidate + // (skip_path=None). Passing Some(path) here excluded the only + // radio on single-device nodes and the mesh never came up. + auto_detect_and_open( + data_dir, + our_ed_pubkey_hex, + our_x25519_pubkey_hex, + device_kind, + None, + Some(&desired_advert_name), + ) + .await + } else { + match open_preferred_path( + path, + data_dir, + our_ed_pubkey_hex, + our_x25519_pubkey_hex, + device_kind, + Some(&desired_advert_name), + ) + .await + { + Ok((dev, info)) => Ok((path.to_string(), dev, info)), + Err(e) => { + warn!( + "Preferred path {} probe failed: {} — trying auto-detect", + path, e + ); + auto_detect_and_open( + data_dir, + our_ed_pubkey_hex, + our_x25519_pubkey_hex, + device_kind, + Some(path), + Some(&desired_advert_name), + ) + .await + } } } } else {