agent: code-atomiser-fix — test_llm_model respects caller GPU preference (Race-8)

Add an Option<bool> use_gpu parameter to test_llm_model with the same
default-true semantics as load_llm_model. Hard-coding true triggered an
engine tear-down/rebuild when a parallel load_llm_model(use_gpu=false)
was in flight (LlmEngine::load_model triples on id+path+use_gpu) and
silently flipped the user's GPU mode underneath the test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 15:12:24 +01:00
parent 5ba761a4b8
commit afbd33d33e
6 changed files with 253 additions and 19 deletions

View File

@@ -5,13 +5,18 @@ mod tauri_app_data_migration;
#[cfg(not(target_os = "android"))]
mod tray;
use std::path::Path;
use std::sync::Arc;
use std::sync::Once;
use std::sync::{Once, OnceLock};
use std::time::Instant;
use sqlx::SqlitePool;
use tauri::Manager;
use tracing_subscriber::EnvFilter;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_appender::rolling::{RollingFileAppender, Rotation};
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{EnvFilter, Layer};
use lumotia_core::paths::{
check_target_ambiguity, migrate_legacy_data_dir, MigrationStatus,
@@ -31,6 +36,13 @@ use lumotia_transcription::LocalEngine;
static TRACING_INIT: Once = Once::new();
/// Parks the non-blocking file-appender's `WorkerGuard` for the process
/// lifetime. Dropping the guard halts the background log-writing thread
/// and discards any pending log lines, so it must outlive every
/// `tracing::*!` call. A `OnceLock` here gives us a free `'static`
/// home and matches the `Once`-guarded init pattern above.
static FILE_APPENDER_GUARD: OnceLock<WorkerGuard> = OnceLock::new();
/// Shared app state holding the transcription engines and database pool.
pub struct AppState {
pub whisper_engine: Arc<LocalEngine>,
@@ -165,18 +177,112 @@ fn warn_if_x11_env_unset_on_wayland() {
}
}
/// Default `EnvFilter` string for the stderr (developer-facing) layer.
///
/// `lumotia_lib::commands::live=info` is listed explicitly so that the
/// operator's documented triage filter (per
/// docs/superpowers/audits/2026-05-10-phase10a-dogfood-notes.md) works
/// without a manual `RUST_LOG=` override on every dogfooding session.
const DEFAULT_STDERR_FILTER: &str =
"warn,lumotia=info,lumotia_lib=info,lumotia_lib::commands::live=info,lumotia_core=info,lumotia_audio=info,lumotia_hotkey=info,lumotia_ai_formatting=info,lumotia_llm=info,lumotia_storage=info,lumotia_transcription=info,lumotia_startup=info";
/// Default `EnvFilter` string for the rolling-file (forensic) layer.
///
/// More verbose than stderr by design: the file is what users attach to
/// diagnostic reports, so DEBUG-level Lumotia internals are worth the
/// disk cost. Third-party crates that spam at DEBUG (`sqlx`, `hyper`,
/// `reqwest`, `h2`, `rustls`, `tokio_util`) are pinned at INFO so they
/// don't drown out our own log lines.
const DEFAULT_FILE_FILTER: &str =
"info,lumotia=debug,lumotia_lib=debug,lumotia_lib::commands::live=debug,lumotia_core=debug,lumotia_audio=debug,lumotia_hotkey=debug,lumotia_ai_formatting=debug,lumotia_llm=debug,lumotia_storage=debug,lumotia_transcription=debug,lumotia_startup=debug,sqlx=info,hyper=info,reqwest=info,h2=info,rustls=info,tokio_util=info";
/// Build the stderr-side `EnvFilter`, honouring `RUST_LOG` if set.
fn stderr_env_filter() -> EnvFilter {
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(DEFAULT_STDERR_FILTER))
}
/// Build the file-side `EnvFilter`, honouring `LUMOTIA_LOG_FILE` if set
/// (falling back to `RUST_LOG`, then the verbose default).
fn file_env_filter() -> EnvFilter {
EnvFilter::try_from_env("LUMOTIA_LOG_FILE")
.or_else(|_| EnvFilter::try_from_default_env())
.unwrap_or_else(|_| EnvFilter::new(DEFAULT_FILE_FILTER))
}
/// Build the rolling daily appender for `lumotia.log` inside `logs_dir`.
///
/// Rotation policy: one file per day, keep 7 most-recent days. Older
/// files are pruned by `tracing-appender` itself. The base filename is
/// `lumotia.log`; rotated files get a date suffix (e.g.
/// `lumotia.log.2026-05-12`).
fn build_rolling_appender(logs_dir: &Path) -> std::io::Result<RollingFileAppender> {
std::fs::create_dir_all(logs_dir)?;
RollingFileAppender::builder()
.rotation(Rotation::DAILY)
.filename_prefix("lumotia")
.filename_suffix("log")
.max_log_files(7)
.build(logs_dir)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))
}
/// Install a `tracing` subscriber that writes to stderr (developer
/// stream, ANSI-coloured) AND to a rolling daily file at
/// `logs_dir/lumotia.log` (forensic stream, plain text). The file
/// stream is what diagnostic-report bundles attach.
///
/// Returns the `WorkerGuard` for the file appender so the caller can
/// park it for the process lifetime; dropping it discards pending logs.
/// Returns `None` if the file appender could not be built (e.g.
/// permissions); in that case only the stderr layer is installed.
///
/// Exposed `pub` so the `tracing_appender_smoke` integration test can
/// drive it against a tempdir; production code calls it via
/// `init_tracing` against the platform-default `logs_dir()`.
pub fn install_subscriber(logs_dir: &Path) -> Option<WorkerGuard> {
let stderr_layer = tracing_subscriber::fmt::layer()
.with_writer(std::io::stderr)
.with_filter(stderr_env_filter());
match build_rolling_appender(logs_dir) {
Ok(appender) => {
let (non_blocking, guard) = tracing_appender::non_blocking(appender);
let file_layer = tracing_subscriber::fmt::layer()
.with_writer(non_blocking)
.with_ansi(false)
.with_filter(file_env_filter());
let _ = tracing_subscriber::registry()
.with(stderr_layer)
.with(file_layer)
.try_init();
Some(guard)
}
Err(e) => {
// Best-effort: keep stderr logging even if the file path is
// unwritable, and surface the failure to stderr so dogfooders
// notice the missing forensic stream.
let _ = tracing_subscriber::registry()
.with(stderr_layer)
.try_init();
eprintln!(
"lumotia: failed to install rolling file log appender at {}: {e}",
logs_dir.display()
);
None
}
}
}
fn init_tracing() {
TRACING_INIT.call_once(|| {
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
EnvFilter::new(
"warn,lumotia=info,lumotia_lib=info,lumotia_core=info,lumotia_audio=info,lumotia_hotkey=info,lumotia_ai_formatting=info,lumotia_llm=info,lumotia_storage=info,lumotia_transcription=info,lumotia_startup=info",
)
});
let _ = tracing_subscriber::fmt()
.with_env_filter(env_filter)
.with_writer(std::io::stderr)
.try_init();
let logs_dir = lumotia_storage::file_storage::logs_dir();
if let Some(guard) = install_subscriber(&logs_dir) {
// Park the guard for the process lifetime. set() only fails
// if already set (impossible inside Once::call_once), so we
// ignore the result.
let _ = FILE_APPENDER_GUARD.set(guard);
}
});
}