From a82d0cc704b5806e3abbd47d3f5b4a9ba756fa2a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 30 Jun 2026 13:12:58 +0000 Subject: [PATCH] Make run_lockstep surface UnknownFamily warnings like check/test do MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit run_lockstep validated stm32.toml via check(), which silently falls back to the F446RE database for an unrecognized [device].family with no indication anything was approximated. check_family() exists specifically to surface that as a warning, and run_check/run_test already use it — run_lockstep now does too, so all three commands behave consistently for an unknown family. --- crates/nucleus-cli/src/main.rs | 9 +++++++-- crates/nucleus-cli/tests/cli.rs | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/crates/nucleus-cli/src/main.rs b/crates/nucleus-cli/src/main.rs index ae0f945..61a646d 100644 --- a/crates/nucleus-cli/src/main.rs +++ b/crates/nucleus-cli/src/main.rs @@ -672,14 +672,19 @@ fn run_lockstep(path: &Path, explain: bool) -> ExitCode { } }; - let check_report = match nucleus_compiler::check(&text) { - Ok(report) => report, + let (check_report, family_warning) = match check_family(&text) { + Ok(result) => result, Err(err) => { print_parse_error(&toml_path, &err); return ExitCode::FAILURE; } }; + if let Some(warning) = &family_warning { + eprintln!("warning: {warning}"); + eprintln!(" falling back to STM32F446RE; results may be inaccurate.\n"); + } + if !check_report.is_ok() { let n = check_report.conflicts.len(); eprintln!( diff --git a/crates/nucleus-cli/tests/cli.rs b/crates/nucleus-cli/tests/cli.rs index 0377235..37a82ec 100644 --- a/crates/nucleus-cli/tests/cli.rs +++ b/crates/nucleus-cli/tests/cli.rs @@ -712,6 +712,28 @@ fn lockstep_with_present_firmware_runs_both_backends_concurrently_without_hangin ); } +#[test] +fn lockstep_warns_on_unknown_family_instead_of_silently_falling_back() { + // Regression test for issue 53: run_lockstep called check() instead of + // check_family(), so an unrecognized [device].family silently validated + // against the F446RE fallback DB with no warning — unlike `check` and + // `test`, which both surface UnknownFamily via check_family()/test_plan(). + let proj = TempProject::new(); + std::fs::write( + proj.path().join("stm32.toml"), + "[device]\nfamily = \"STM32H750\"\n", + ) + .unwrap(); + + let out = nucleus(&["lockstep".as_ref(), proj.path().as_os_str()]); + + let stderr = String::from_utf8_lossy(&out.stderr); + assert!( + stderr.contains("unsupported device family"), + "expected an UnknownFamily warning, got stderr:\n{stderr}" + ); +} + #[test] fn init_rejects_unknown_board() { let proj = TempProject::new();