agent: lumotia-rebrand — fix QC blockers for phase 2
Phase 2 QC found three explicit blockers + a broader sweep needed:
Explicit (QC-named):
- crates/mcp/src/lib.rs:15 — SERVER_NAME public MCP wire identity
- crates/transcription/build.rs:59 — panic message prefix
- crates/llm/tests/content_tags_smoke.rs:7 — docstring -p flag
Swept (string literals + dev env vars + doc comments + test fixtures):
- crates/mcp/src/main.rs — eprintln log prefixes
- src-tauri/src/commands/diagnostics.rs — diagnostic filename + MAGNOTIA_VERSION
- src-tauri/src/commands/audio.rs — recording filename pattern lumotia-<secs>-...wav
- src-tauri/src/commands/fs.rs — test placeholder path
- crates/transcription/src/model_manager.rs — .lumotia-verified marker
- crates/storage/src/database.rs — lumotia-storage-ro-<pid> temp dirs + doc comments
- crates/cloud-providers/src/keystore.rs — LUMOTIA_API_KEY_<PROVIDER> env var
- crates/audio/src/{wav,decode}.rs — lumotia_test_* / lumotia_decode_* test fixtures
- crates/core/src/tuning.rs — LUMOTIA_INFERENCE_THREADS env var
- All MAGNOTIA_LLM_TEST_MODEL / MAGNOTIA_WHISPER_TEST_* env vars
- Doc comments referencing crate names
Excluded (intentional Phase 4/5 scope):
- magnotia_preferences, magnotia_history, magnotia_morning_triage_last_shown
DB setting keys (Phase 5 paths.rs migration)
- magnotia_startup tracing target (Phase 4)
- crates/core/src/paths.rs (Phase 5 wholesale rewrite + migration shim)
cargo build --workspace passes. cargo test --workspace: 330 pass, 0 fail.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -191,7 +191,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn valid_wav_bytes(sample_count: usize) -> Vec<u8> {
|
fn valid_wav_bytes(sample_count: usize) -> Vec<u8> {
|
||||||
let path = temp_path("magnotia_decode_tmp_for_bytes.wav");
|
let path = temp_path("lumotia_decode_tmp_for_bytes.wav");
|
||||||
let samples: Vec<f32> = (0..sample_count).map(|i| (i as f32) / 1000.0).collect();
|
let samples: Vec<f32> = (0..sample_count).map(|i| (i as f32) / 1000.0).collect();
|
||||||
let audio = AudioSamples::mono_16khz(samples);
|
let audio = AudioSamples::mono_16khz(samples);
|
||||||
write_wav(&path, &audio).unwrap();
|
write_wav(&path, &audio).unwrap();
|
||||||
@@ -238,7 +238,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decodes_valid_wav_successfully() {
|
fn decodes_valid_wav_successfully() {
|
||||||
let path = temp_path("magnotia_decode_valid.wav");
|
let path = temp_path("lumotia_decode_valid.wav");
|
||||||
let samples: Vec<f32> = (0..4_000).map(|i| (i as f32) / 1000.0).collect();
|
let samples: Vec<f32> = (0..4_000).map(|i| (i as f32) / 1000.0).collect();
|
||||||
write_wav(&path, &AudioSamples::mono_16khz(samples)).unwrap();
|
write_wav(&path, &AudioSamples::mono_16khz(samples)).unwrap();
|
||||||
|
|
||||||
@@ -251,7 +251,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn missing_file_surfaces_error() {
|
fn missing_file_surfaces_error() {
|
||||||
let path = temp_path("magnotia_decode_missing.wav");
|
let path = temp_path("lumotia_decode_missing.wav");
|
||||||
let result = decode_audio_file(&path);
|
let result = decode_audio_file(&path);
|
||||||
assert!(result.is_err(), "missing file must error, got: {result:?}");
|
assert!(result.is_err(), "missing file must error, got: {result:?}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ mod tests {
|
|||||||
// mirrors what happens when the OS reaps the process without
|
// mirrors what happens when the OS reaps the process without
|
||||||
// giving Rust a chance to run destructors.
|
// giving Rust a chance to run destructors.
|
||||||
let temp_dir = std::env::temp_dir();
|
let temp_dir = std::env::temp_dir();
|
||||||
let path = temp_dir.join("magnotia_test_wav_writer_survives_crash.wav");
|
let path = temp_dir.join("lumotia_test_wav_writer_survives_crash.wav");
|
||||||
let _ = std::fs::remove_file(&path);
|
let _ = std::fs::remove_file(&path);
|
||||||
|
|
||||||
let mut writer = WavWriter::create(&path, 16_000, 1).unwrap();
|
let mut writer = WavWriter::create(&path, 16_000, 1).unwrap();
|
||||||
@@ -219,7 +219,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn wav_writer_append_then_finalize_roundtrips() {
|
fn wav_writer_append_then_finalize_roundtrips() {
|
||||||
let temp_dir = std::env::temp_dir();
|
let temp_dir = std::env::temp_dir();
|
||||||
let path = temp_dir.join("magnotia_test_wav_writer_finalize.wav");
|
let path = temp_dir.join("lumotia_test_wav_writer_finalize.wav");
|
||||||
let _ = std::fs::remove_file(&path);
|
let _ = std::fs::remove_file(&path);
|
||||||
|
|
||||||
let mut writer = WavWriter::create(&path, 16_000, 1).unwrap();
|
let mut writer = WavWriter::create(&path, 16_000, 1).unwrap();
|
||||||
@@ -241,7 +241,7 @@ mod tests {
|
|||||||
// truncated WAV returned Ok with a short samples vec. The
|
// truncated WAV returned Ok with a short samples vec. The
|
||||||
// new code must propagate the error.
|
// new code must propagate the error.
|
||||||
let temp_dir = std::env::temp_dir();
|
let temp_dir = std::env::temp_dir();
|
||||||
let path = temp_dir.join("magnotia_test_truncated_wav.wav");
|
let path = temp_dir.join("lumotia_test_truncated_wav.wav");
|
||||||
let _ = std::fs::remove_file(&path);
|
let _ = std::fs::remove_file(&path);
|
||||||
|
|
||||||
// Write 100 samples (200 bytes at 16-bit).
|
// Write 100 samples (200 bytes at 16-bit).
|
||||||
@@ -267,7 +267,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn wav_roundtrip() {
|
fn wav_roundtrip() {
|
||||||
let temp_dir = std::env::temp_dir();
|
let temp_dir = std::env::temp_dir();
|
||||||
let path = temp_dir.join("magnotia_test_roundtrip.wav");
|
let path = temp_dir.join("lumotia_test_roundtrip.wav");
|
||||||
|
|
||||||
let original = AudioSamples::mono_16khz(vec![0.0, 0.5, -0.5, 0.25, -0.25]);
|
let original = AudioSamples::mono_16khz(vec![0.0, 0.5, -0.5, 0.25, -0.25]);
|
||||||
write_wav(&path, &original).unwrap();
|
write_wav(&path, &original).unwrap();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::sync::{Mutex, OnceLock};
|
|||||||
/// exit. This avoids the undefined behaviour of mutating process environment
|
/// exit. This avoids the undefined behaviour of mutating process environment
|
||||||
/// variables from arbitrary threads while keeping the public API safe.
|
/// variables from arbitrary threads while keeping the public API safe.
|
||||||
///
|
///
|
||||||
/// `retrieve_api_key` still falls back to `MAGNOTIA_API_KEY_<PROVIDER>` environment
|
/// `retrieve_api_key` still falls back to `LUMOTIA_API_KEY_<PROVIDER>` environment
|
||||||
/// variables so externally injected secrets continue to work.
|
/// variables so externally injected secrets continue to work.
|
||||||
///
|
///
|
||||||
/// TODO: Replace with the `keyring` crate (or platform-native credential
|
/// TODO: Replace with the `keyring` crate (or platform-native credential
|
||||||
@@ -22,7 +22,7 @@ pub fn store_api_key(provider: &str, key: &str) {
|
|||||||
/// Retrieve an API key from Magnotia's process-local keystore.
|
/// Retrieve an API key from Magnotia's process-local keystore.
|
||||||
///
|
///
|
||||||
/// Returns a previously stored in-memory key when present, otherwise falls
|
/// Returns a previously stored in-memory key when present, otherwise falls
|
||||||
/// back to the read-only `MAGNOTIA_API_KEY_<PROVIDER>` environment variable so
|
/// back to the read-only `LUMOTIA_API_KEY_<PROVIDER>` environment variable so
|
||||||
/// operator-supplied secrets still work.
|
/// operator-supplied secrets still work.
|
||||||
pub fn retrieve_api_key(provider: &str) -> Option<String> {
|
pub fn retrieve_api_key(provider: &str) -> Option<String> {
|
||||||
let env_key = provider_env_key(provider);
|
let env_key = provider_env_key(provider);
|
||||||
@@ -40,7 +40,7 @@ fn api_key_store() -> &'static Mutex<HashMap<String, String>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn provider_env_key(provider: &str) -> String {
|
fn provider_env_key(provider: &str) -> String {
|
||||||
format!("MAGNOTIA_API_KEY_{}", provider.to_uppercase())
|
format!("LUMOTIA_API_KEY_{}", provider.to_uppercase())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
//! `TranscriptionProvider` is the async-native trait every transcription
|
//! `TranscriptionProvider` is the async-native trait every transcription
|
||||||
//! backend implements, regardless of whether the work happens locally
|
//! backend implements, regardless of whether the work happens locally
|
||||||
//! (Whisper, Parakeet, Moonshine via the `LocalProviderAdapter` in
|
//! (Whisper, Parakeet, Moonshine via the `LocalProviderAdapter` in
|
||||||
//! `magnotia-transcription`) or remotely (OpenAI Whisper, Groq,
|
//! `lumotia-transcription`) or remotely (OpenAI Whisper, Groq,
|
||||||
//! Deepgram, etc.).
|
//! Deepgram, etc.).
|
||||||
//!
|
//!
|
||||||
//! Living in `magnotia-cloud-providers` is deliberate: the AGPL OEM
|
//! Living in `lumotia-cloud-providers` is deliberate: the AGPL OEM
|
||||||
//! exception (≥£2k/yr) requires a clean trait surface that an OEM
|
//! exception (≥£2k/yr) requires a clean trait surface that an OEM
|
||||||
//! licensee can implement without depending on Wyrdnote's transcription
|
//! licensee can implement without depending on Wyrdnote's transcription
|
||||||
//! internals. The trait crate stays small; provider implementations
|
//! internals. The trait crate stays small; provider implementations
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//! gpu_offloaded) tuples.
|
//! gpu_offloaded) tuples.
|
||||||
//!
|
//!
|
||||||
//! Run with:
|
//! Run with:
|
||||||
//! cargo run -p magnotia-core --example tuning_log_demo
|
//! cargo run -p lumotia-core --example tuning_log_demo
|
||||||
//!
|
//!
|
||||||
//! Output is to stderr (tracing's default). Each unique tuple emits
|
//! Output is to stderr (tracing's default). Each unique tuple emits
|
||||||
//! exactly one INFO line; subsequent calls with the same tuple are
|
//! exactly one INFO line; subsequent calls with the same tuple are
|
||||||
@@ -28,8 +28,8 @@ fn main() {
|
|||||||
("No override (real sysfs probe)", None),
|
("No override (real sysfs probe)", None),
|
||||||
] {
|
] {
|
||||||
match override_value {
|
match override_value {
|
||||||
Some(v) => std::env::set_var("MAGNOTIA_POWER_STATE_OVERRIDE", v),
|
Some(v) => std::env::set_var("LUMOTIA_POWER_STATE_OVERRIDE", v),
|
||||||
None => std::env::remove_var("MAGNOTIA_POWER_STATE_OVERRIDE"),
|
None => std::env::remove_var("LUMOTIA_POWER_STATE_OVERRIDE"),
|
||||||
}
|
}
|
||||||
// Cache invalidation so the live probe re-runs each section.
|
// Cache invalidation so the live probe re-runs each section.
|
||||||
// Override paths bypass the cache anyway; this is for the
|
// Override paths bypass the cache anyway; this is for the
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ pub(crate) fn force_set_cache(state: PowerState) {
|
|||||||
///
|
///
|
||||||
/// Resolution order (highest to lowest priority):
|
/// Resolution order (highest to lowest priority):
|
||||||
/// 1. In-process test override (set via `with_override` from unit tests).
|
/// 1. In-process test override (set via `with_override` from unit tests).
|
||||||
/// 2. `MAGNOTIA_POWER_STATE_OVERRIDE` env var (`ac` | `battery` | `unknown`,
|
/// 2. `LUMOTIA_POWER_STATE_OVERRIDE` env var (`ac` | `battery` | `unknown`,
|
||||||
/// case-insensitive). Used by `thread_sweep.rs` integration tests.
|
/// case-insensitive). Used by `thread_sweep.rs` integration tests.
|
||||||
/// 3. Linux: `parse_power_state_from_dir("/sys/class/power_supply")`.
|
/// 3. Linux: `parse_power_state_from_dir("/sys/class/power_supply")`.
|
||||||
/// 4. macOS / Windows / other: `Unknown`.
|
/// 4. macOS / Windows / other: `Unknown`.
|
||||||
@@ -136,7 +136,7 @@ pub fn probe_power_state() -> PowerState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn env_override() -> Option<PowerState> {
|
fn env_override() -> Option<PowerState> {
|
||||||
let raw = std::env::var("MAGNOTIA_POWER_STATE_OVERRIDE").ok()?;
|
let raw = std::env::var("LUMOTIA_POWER_STATE_OVERRIDE").ok()?;
|
||||||
match raw.trim().to_ascii_lowercase().as_str() {
|
match raw.trim().to_ascii_lowercase().as_str() {
|
||||||
"ac" => Some(PowerState::OnAc),
|
"ac" => Some(PowerState::OnAc),
|
||||||
"battery" => Some(PowerState::OnBattery),
|
"battery" => Some(PowerState::OnBattery),
|
||||||
@@ -293,21 +293,21 @@ mod tests {
|
|||||||
// env-var path tested in isolation under TEST_LOCK so it
|
// env-var path tested in isolation under TEST_LOCK so it
|
||||||
// doesn't race with the in-process override tests.
|
// doesn't race with the in-process override tests.
|
||||||
with_override(None, || {
|
with_override(None, || {
|
||||||
std::env::set_var("MAGNOTIA_POWER_STATE_OVERRIDE", "battery");
|
std::env::set_var("LUMOTIA_POWER_STATE_OVERRIDE", "battery");
|
||||||
assert_eq!(probe_power_state(), PowerState::OnBattery);
|
assert_eq!(probe_power_state(), PowerState::OnBattery);
|
||||||
std::env::remove_var("MAGNOTIA_POWER_STATE_OVERRIDE");
|
std::env::remove_var("LUMOTIA_POWER_STATE_OVERRIDE");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn env_var_override_garbage_falls_through() {
|
fn env_var_override_garbage_falls_through() {
|
||||||
with_override(None, || {
|
with_override(None, || {
|
||||||
std::env::set_var("MAGNOTIA_POWER_STATE_OVERRIDE", "nonsense");
|
std::env::set_var("LUMOTIA_POWER_STATE_OVERRIDE", "nonsense");
|
||||||
// Garbage value falls through to the platform probe.
|
// Garbage value falls through to the platform probe.
|
||||||
// We can't assert the platform result so just assert it
|
// We can't assert the platform result so just assert it
|
||||||
// doesn't panic.
|
// doesn't panic.
|
||||||
let _ = probe_power_state();
|
let _ = probe_power_state();
|
||||||
std::env::remove_var("MAGNOTIA_POWER_STATE_OVERRIDE");
|
std::env::remove_var("LUMOTIA_POWER_STATE_OVERRIDE");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub const MIN_INFERENCE_THREADS: usize = 2;
|
|||||||
/// 8 is a conservative ceiling that leaves <5% on the table for
|
/// 8 is a conservative ceiling that leaves <5% on the table for
|
||||||
/// big-iron desktops while keeping consumer 6c/12t laptops out of
|
/// big-iron desktops while keeping consumer 6c/12t laptops out of
|
||||||
/// contention territory. Users can override at runtime via
|
/// contention territory. Users can override at runtime via
|
||||||
/// MAGNOTIA_INFERENCE_THREADS.
|
/// LUMOTIA_INFERENCE_THREADS.
|
||||||
pub const MAX_INFERENCE_THREADS: usize = 8;
|
pub const MAX_INFERENCE_THREADS: usize = 8;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
@@ -45,13 +45,13 @@ fn log_seen() -> &'static Mutex<HashSet<(Workload, bool, bool)>> {
|
|||||||
/// the battery and GPU-offload heuristics.
|
/// the battery and GPU-offload heuristics.
|
||||||
///
|
///
|
||||||
/// Resolution order:
|
/// Resolution order:
|
||||||
/// 1. `MAGNOTIA_INFERENCE_THREADS=N` — absolute bypass, returns N.
|
/// 1. `LUMOTIA_INFERENCE_THREADS=N` — absolute bypass, returns N.
|
||||||
/// 2. base = num_cpus::get_physical() (fallback: available_parallelism).
|
/// 2. base = num_cpus::get_physical() (fallback: available_parallelism).
|
||||||
/// 3. on battery → base /= 2.
|
/// 3. on battery → base /= 2.
|
||||||
/// 4. gpu_offloaded → base = min(base, gpu_floor(workload)).
|
/// 4. gpu_offloaded → base = min(base, gpu_floor(workload)).
|
||||||
/// 5. clamp to [MIN_INFERENCE_THREADS, MAX_INFERENCE_THREADS].
|
/// 5. clamp to [MIN_INFERENCE_THREADS, MAX_INFERENCE_THREADS].
|
||||||
pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize {
|
pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize {
|
||||||
if let Ok(s) = std::env::var("MAGNOTIA_INFERENCE_THREADS") {
|
if let Ok(s) = std::env::var("LUMOTIA_INFERENCE_THREADS") {
|
||||||
if let Ok(n) = s.parse::<usize>() {
|
if let Ok(n) = s.parse::<usize>() {
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
return n;
|
return n;
|
||||||
@@ -107,7 +107,7 @@ pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Serialises tests that read/write `MAGNOTIA_INFERENCE_THREADS` so
|
/// Serialises tests that read/write `LUMOTIA_INFERENCE_THREADS` so
|
||||||
/// they don't race under cargo's parallel test runner.
|
/// they don't race under cargo's parallel test runner.
|
||||||
/// Mirrors the pattern used by `power::with_override`.
|
/// Mirrors the pattern used by `power::with_override`.
|
||||||
fn with_thread_env_lock<R>(body: impl FnOnce() -> R) -> R {
|
fn with_thread_env_lock<R>(body: impl FnOnce() -> R) -> R {
|
||||||
@@ -126,7 +126,7 @@ mod tests {
|
|||||||
// We can't pin physical exactly without mocking num_cpus; just
|
// We can't pin physical exactly without mocking num_cpus; just
|
||||||
// assert the result is in range.
|
// assert the result is in range.
|
||||||
with_thread_env_lock(|| {
|
with_thread_env_lock(|| {
|
||||||
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
|
std::env::remove_var("LUMOTIA_INFERENCE_THREADS");
|
||||||
let n = inference_thread_count(Workload::Llm, false);
|
let n = inference_thread_count(Workload::Llm, false);
|
||||||
assert!(
|
assert!(
|
||||||
(MIN_INFERENCE_THREADS..=MAX_INFERENCE_THREADS).contains(&n),
|
(MIN_INFERENCE_THREADS..=MAX_INFERENCE_THREADS).contains(&n),
|
||||||
@@ -138,10 +138,10 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn env_var_bypasses_clamps() {
|
fn env_var_bypasses_clamps() {
|
||||||
with_thread_env_lock(|| {
|
with_thread_env_lock(|| {
|
||||||
std::env::set_var("MAGNOTIA_INFERENCE_THREADS", "10");
|
std::env::set_var("LUMOTIA_INFERENCE_THREADS", "10");
|
||||||
let n = inference_thread_count(Workload::Llm, true);
|
let n = inference_thread_count(Workload::Llm, true);
|
||||||
assert_eq!(n, 10);
|
assert_eq!(n, 10);
|
||||||
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
|
std::env::remove_var("LUMOTIA_INFERENCE_THREADS");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn battery_halves_thread_count() {
|
fn battery_halves_thread_count() {
|
||||||
with_thread_env_lock(|| {
|
with_thread_env_lock(|| {
|
||||||
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
|
std::env::remove_var("LUMOTIA_INFERENCE_THREADS");
|
||||||
// Measure on battery, then on AC — sequential, not nested,
|
// Measure on battery, then on AC — sequential, not nested,
|
||||||
// to avoid re-entrant deadlock on power::TEST_LOCK.
|
// to avoid re-entrant deadlock on power::TEST_LOCK.
|
||||||
let on_battery = crate::power::with_override(Some(PowerState::OnBattery), || {
|
let on_battery = crate::power::with_override(Some(PowerState::OnBattery), || {
|
||||||
@@ -176,7 +176,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn gpu_offload_clamps_llm_to_floor() {
|
fn gpu_offload_clamps_llm_to_floor() {
|
||||||
with_thread_env_lock(|| {
|
with_thread_env_lock(|| {
|
||||||
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
|
std::env::remove_var("LUMOTIA_INFERENCE_THREADS");
|
||||||
crate::power::with_override(Some(PowerState::OnAc), || {
|
crate::power::with_override(Some(PowerState::OnAc), || {
|
||||||
let n = inference_thread_count(Workload::Llm, true);
|
let n = inference_thread_count(Workload::Llm, true);
|
||||||
assert!(
|
assert!(
|
||||||
@@ -191,7 +191,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn gpu_offload_clamps_whisper_to_floor() {
|
fn gpu_offload_clamps_whisper_to_floor() {
|
||||||
with_thread_env_lock(|| {
|
with_thread_env_lock(|| {
|
||||||
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
|
std::env::remove_var("LUMOTIA_INFERENCE_THREADS");
|
||||||
crate::power::with_override(Some(PowerState::OnAc), || {
|
crate::power::with_override(Some(PowerState::OnAc), || {
|
||||||
let n = inference_thread_count(Workload::Whisper, true);
|
let n = inference_thread_count(Workload::Whisper, true);
|
||||||
// Whisper floor is 4 on machines with >=4 physical cores;
|
// Whisper floor is 4 on machines with >=4 physical cores;
|
||||||
@@ -213,7 +213,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn gpu_offload_off_does_not_clamp_below_battery_calc() {
|
fn gpu_offload_off_does_not_clamp_below_battery_calc() {
|
||||||
with_thread_env_lock(|| {
|
with_thread_env_lock(|| {
|
||||||
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
|
std::env::remove_var("LUMOTIA_INFERENCE_THREADS");
|
||||||
// Sequential measurements; with_override is non-reentrant.
|
// Sequential measurements; with_override is non-reentrant.
|
||||||
crate::power::with_override(Some(PowerState::OnAc), || {
|
crate::power::with_override(Some(PowerState::OnAc), || {
|
||||||
let no_gpu = inference_thread_count(Workload::Llm, false);
|
let no_gpu = inference_thread_count(Workload::Llm, false);
|
||||||
@@ -230,7 +230,7 @@ mod tests {
|
|||||||
// wired. This is covered by the other tests too, but kept
|
// wired. This is covered by the other tests too, but kept
|
||||||
// explicitly to document the behaviour.
|
// explicitly to document the behaviour.
|
||||||
with_thread_env_lock(|| {
|
with_thread_env_lock(|| {
|
||||||
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
|
std::env::remove_var("LUMOTIA_INFERENCE_THREADS");
|
||||||
crate::power::with_override(Some(PowerState::OnBattery), || {
|
crate::power::with_override(Some(PowerState::OnBattery), || {
|
||||||
let _ = inference_thread_count(Workload::Llm, true);
|
let _ = inference_thread_count(Workload::Llm, true);
|
||||||
let _ = inference_thread_count(Workload::Whisper, false);
|
let _ = inference_thread_count(Workload::Whisper, false);
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ context that are not explicit commitments. Output an empty array if there are \
|
|||||||
no action items.";
|
no action items.";
|
||||||
|
|
||||||
/// Compact representation of a human-in-the-loop feedback example used
|
/// Compact representation of a human-in-the-loop feedback example used
|
||||||
/// for few-shot prompt conditioning. Built by magnotia-storage and fed to the
|
/// for few-shot prompt conditioning. Built by lumotia-storage and fed to the
|
||||||
/// prompt builder below; we keep this struct local to the LLM crate so
|
/// prompt builder below; we keep this struct local to the LLM crate so
|
||||||
/// magnotia-llm does not depend on magnotia-storage.
|
/// lumotia-llm does not depend on lumotia-storage.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FeedbackExample {
|
pub struct FeedbackExample {
|
||||||
/// What the AI was given as input (e.g. the parent task text, or
|
/// What the AI was given as input (e.g. the parent task text, or
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
//! Smoke test for Phase 9 LlmEngine::extract_content_tags.
|
//! Smoke test for Phase 9 LlmEngine::extract_content_tags.
|
||||||
//!
|
//!
|
||||||
//! Gated behind the same `MAGNOTIA_LLM_TEST_MODEL` env var as the existing
|
//! Gated behind the same `LUMOTIA_LLM_TEST_MODEL` env var as the existing
|
||||||
//! smoke.rs test so neither runs in default `cargo test` runs (model
|
//! smoke.rs test so neither runs in default `cargo test` runs (model
|
||||||
//! load is heavy). Run explicitly with:
|
//! load is heavy). Run explicitly with:
|
||||||
//!
|
//!
|
||||||
//! MAGNOTIA_LLM_TEST_MODEL=/path/to/model.gguf cargo test -p magnotia-llm \
|
//! LUMOTIA_LLM_TEST_MODEL=/path/to/model.gguf cargo test -p lumotia-llm \
|
||||||
//! --test content_tags_smoke -- --nocapture
|
//! --test content_tags_smoke -- --nocapture
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
@@ -14,10 +14,10 @@ use lumotia_llm::{is_valid_intent, LlmEngine, LlmModelId};
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn extract_content_tags_returns_valid_pair() {
|
fn extract_content_tags_returns_valid_pair() {
|
||||||
let model_path = match env::var("MAGNOTIA_LLM_TEST_MODEL") {
|
let model_path = match env::var("LUMOTIA_LLM_TEST_MODEL") {
|
||||||
Ok(path) => PathBuf::from(path),
|
Ok(path) => PathBuf::from(path),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("MAGNOTIA_LLM_TEST_MODEL not set — skipping");
|
eprintln!("LUMOTIA_LLM_TEST_MODEL not set — skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//! - `context::params::LlamaContextParams`
|
//! - `context::params::LlamaContextParams`
|
||||||
//! - `sampling::LlamaSampler`
|
//! - `sampling::LlamaSampler`
|
||||||
//!
|
//!
|
||||||
//! The test is gated behind `MAGNOTIA_LLM_TEST_MODEL`.
|
//! The test is gated behind `LUMOTIA_LLM_TEST_MODEL`.
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -16,10 +16,10 @@ use lumotia_llm::LlmModelId;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn llama_cpp_2_smoke_generates_and_wraps() {
|
fn llama_cpp_2_smoke_generates_and_wraps() {
|
||||||
let model_path = match env::var("MAGNOTIA_LLM_TEST_MODEL") {
|
let model_path = match env::var("LUMOTIA_LLM_TEST_MODEL") {
|
||||||
Ok(path) => PathBuf::from(path),
|
Ok(path) => PathBuf::from(path),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("MAGNOTIA_LLM_TEST_MODEL not set — skipping");
|
eprintln!("LUMOTIA_LLM_TEST_MODEL not set — skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use serde_json::{json, Value};
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
pub const PROTOCOL_VERSION: &str = "2024-11-05";
|
pub const PROTOCOL_VERSION: &str = "2024-11-05";
|
||||||
pub const SERVER_NAME: &str = "magnotia-mcp";
|
pub const SERVER_NAME: &str = "lumotia-mcp";
|
||||||
pub const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! Stdio entry point for magnotia-mcp. Reads newline-delimited JSON-RPC messages
|
//! Stdio entry point for lumotia-mcp. Reads newline-delimited JSON-RPC messages
|
||||||
//! from stdin, dispatches via `lumotia_mcp::handle_message`, writes responses to
|
//! from stdin, dispatches via `lumotia_mcp::handle_message`, writes responses to
|
||||||
//! stdout. Logs land on stderr so they don't collide with the JSON-RPC stream.
|
//! stdout. Logs land on stderr so they don't collide with the JSON-RPC stream.
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
|||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
let db_path = lumotia_storage::database_path();
|
let db_path = lumotia_storage::database_path();
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"[magnotia-mcp] opening Magnotia database at {} (read-only)",
|
"[lumotia-mcp] opening Lumotia database at {} (read-only)",
|
||||||
db_path.display()
|
db_path.display()
|
||||||
);
|
);
|
||||||
// Open read-only at the connection level so the MCP server cannot write
|
// Open read-only at the connection level so the MCP server cannot write
|
||||||
@@ -16,7 +16,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
// exposes. Migrations are deliberately skipped — this binary never owns
|
// exposes. Migrations are deliberately skipped — this binary never owns
|
||||||
// the schema; the main app is the single migration writer.
|
// the schema; the main app is the single migration writer.
|
||||||
let pool = lumotia_storage::init_readonly(&db_path).await?;
|
let pool = lumotia_storage::init_readonly(&db_path).await?;
|
||||||
eprintln!("[magnotia-mcp] ready, waiting for JSON-RPC on stdin");
|
eprintln!("[lumotia-mcp] ready, waiting for JSON-RPC on stdin");
|
||||||
|
|
||||||
let mut lines = BufReader::new(tokio::io::stdin()).lines();
|
let mut lines = BufReader::new(tokio::io::stdin()).lines();
|
||||||
let mut stdout = tokio::io::stdout();
|
let mut stdout = tokio::io::stdout();
|
||||||
@@ -38,7 +38,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
// logged and continued, dropping the response —
|
// logged and continued, dropping the response —
|
||||||
// clients saw silence instead of a structured error
|
// clients saw silence instead of a structured error
|
||||||
// (2026-04-22 review MAJOR).
|
// (2026-04-22 review MAJOR).
|
||||||
eprintln!("[magnotia-mcp] parse error: {err}");
|
eprintln!("[lumotia-mcp] parse error: {err}");
|
||||||
lumotia_mcp::parse_error_response(&err.to_string())
|
lumotia_mcp::parse_error_response(&err.to_string())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ pub async fn init(db_path: &Path) -> Result<SqlitePool> {
|
|||||||
|
|
||||||
/// Open the SQLite database in read-only mode without running migrations.
|
/// Open the SQLite database in read-only mode without running migrations.
|
||||||
///
|
///
|
||||||
/// Used by `magnotia-mcp` so the MCP server cannot write to the user's database
|
/// Used by `lumotia-mcp` so the MCP server cannot write to the user's database
|
||||||
/// regardless of which tools the dispatcher exposes — `read_only(true)` makes
|
/// regardless of which tools the dispatcher exposes — `read_only(true)` makes
|
||||||
/// the constraint structural rather than relying on the request handler being
|
/// the constraint structural rather than relying on the request handler being
|
||||||
/// well-behaved. Fails cleanly if the DB doesn't exist (no `create_if_missing`).
|
/// well-behaved. Fails cleanly if the DB doesn't exist (no `create_if_missing`).
|
||||||
@@ -1384,7 +1384,7 @@ pub async fn list_recent_errors(pool: &SqlitePool, limit: i64) -> Result<Vec<Err
|
|||||||
// Phase 2 of the feature-complete roadmap: capture thumbs + corrections on
|
// Phase 2 of the feature-complete roadmap: capture thumbs + corrections on
|
||||||
// AI-generated output so the prompt builder can inject recent examples as
|
// AI-generated output so the prompt builder can inject recent examples as
|
||||||
// few-shot exemplars. Storage-only here; the prompt-conditioning logic lives
|
// few-shot exemplars. Storage-only here; the prompt-conditioning logic lives
|
||||||
// in magnotia-llm. Retrieval returns the most recent rows, narrowed to the
|
// in lumotia-llm. Retrieval returns the most recent rows, narrowed to the
|
||||||
// active profile when provided so feedback does not cross profiles.
|
// active profile when provided so feedback does not cross profiles.
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@@ -2617,7 +2617,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn init_readonly_rejects_writes_and_serves_reads() {
|
async fn init_readonly_rejects_writes_and_serves_reads() {
|
||||||
let dir = std::env::temp_dir().join(format!("magnotia-storage-ro-{}", std::process::id()));
|
let dir = std::env::temp_dir().join(format!("lumotia-storage-ro-{}", std::process::id()));
|
||||||
std::fs::create_dir_all(&dir).unwrap();
|
std::fs::create_dir_all(&dir).unwrap();
|
||||||
let path = dir.join("ro.db");
|
let path = dir.join("ro.db");
|
||||||
let _ = std::fs::remove_file(&path);
|
let _ = std::fs::remove_file(&path);
|
||||||
@@ -2669,7 +2669,7 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn init_readonly_fails_when_db_missing() {
|
async fn init_readonly_fails_when_db_missing() {
|
||||||
let path = std::env::temp_dir().join(format!(
|
let path = std::env::temp_dir().join(format!(
|
||||||
"magnotia-storage-ro-missing-{}.db",
|
"lumotia-storage-ro-missing-{}.db",
|
||||||
std::process::id()
|
std::process::id()
|
||||||
));
|
));
|
||||||
let _ = std::fs::remove_file(&path);
|
let _ = std::fs::remove_file(&path);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ fn main() {
|
|||||||
|
|
||||||
if target_os == "windows" {
|
if target_os == "windows" {
|
||||||
panic!(
|
panic!(
|
||||||
"magnotia-transcription: the `tokenizers` crate appears in Cargo.lock and this is a \
|
"lumotia-transcription: the `tokenizers` crate appears in Cargo.lock and this is a \
|
||||||
Windows build. Linking `whisper-rs-sys` + `tokenizers` in the same binary has \
|
Windows build. Linking `whisper-rs-sys` + `tokenizers` in the same binary has \
|
||||||
been a persistent MSVC C-runtime conflict (see Whispering v7.11.0). Route any \
|
been a persistent MSVC C-runtime conflict (see Whispering v7.11.0). Route any \
|
||||||
tokenizer usage through an out-of-process sidecar instead, or gate it off for \
|
tokenizer usage through an out-of-process sidecar instead, or gate it off for \
|
||||||
@@ -65,7 +65,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"cargo:warning=magnotia-transcription: `tokenizers` crate is in the dependency graph. \
|
"cargo:warning=lumotia-transcription: `tokenizers` crate is in the dependency graph. \
|
||||||
This build is non-Windows so the link will succeed, but Windows builds will panic \
|
This build is non-Windows so the link will succeed, but Windows builds will panic \
|
||||||
at build time per docs/whisper-ecosystem/brief.md item #6. Isolate tokenizer usage \
|
at build time per docs/whisper-ecosystem/brief.md item #6. Isolate tokenizer usage \
|
||||||
in a sidecar before a Windows ship."
|
in a sidecar before a Windows ship."
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ pub fn list_downloaded() -> Vec<ModelId> {
|
|||||||
/// For files that declare a `sha256` checksum we validate an existing
|
/// For files that declare a `sha256` checksum we validate an existing
|
||||||
/// complete file before skipping the download — a truncated or
|
/// complete file before skipping the download — a truncated or
|
||||||
/// tampered file gets redownloaded automatically (pattern ported from
|
/// tampered file gets redownloaded automatically (pattern ported from
|
||||||
/// `magnotia-llm`'s model_manager, item #8 in the Whisper ecosystem brief).
|
/// `lumotia-llm`'s model_manager, item #8 in the Whisper ecosystem brief).
|
||||||
pub async fn download(
|
pub async fn download(
|
||||||
id: &ModelId,
|
id: &ModelId,
|
||||||
progress: impl Fn(DownloadProgress) + Send + 'static,
|
progress: impl Fn(DownloadProgress) + Send + 'static,
|
||||||
@@ -113,7 +113,7 @@ pub async fn download(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn verified_manifest_path(dir: &Path) -> PathBuf {
|
fn verified_manifest_path(dir: &Path) -> PathBuf {
|
||||||
dir.join(".magnotia-verified")
|
dir.join(".lumotia-verified")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verified_manifest_matches(
|
fn verified_manifest_matches(
|
||||||
@@ -220,7 +220,7 @@ async fn download_file(
|
|||||||
// If we requested Range but the server returned 200 (full file), the
|
// If we requested Range but the server returned 200 (full file), the
|
||||||
// server does not support resume. Rather than blindly appending a
|
// server does not support resume. Rather than blindly appending a
|
||||||
// full file on top of our partial bytes (which would produce a
|
// full file on top of our partial bytes (which would produce a
|
||||||
// corrupt result), restart cleanly. This mirrors the magnotia-llm
|
// corrupt result), restart cleanly. This mirrors the lumotia-llm
|
||||||
// ResumeUnsupported branch — item #8 of the brief.
|
// ResumeUnsupported branch — item #8 of the brief.
|
||||||
//
|
//
|
||||||
// For the non-resume path, we still have to validate the status:
|
// For the non-resume path, we still have to validate the status:
|
||||||
|
|||||||
@@ -2,20 +2,20 @@
|
|||||||
//! Reports cold-load time, transcribe time, RTF, peak RSS.
|
//! Reports cold-load time, transcribe time, RTF, peak RSS.
|
||||||
//!
|
//!
|
||||||
//! Gated on env vars so it never runs in CI without setup:
|
//! Gated on env vars so it never runs in CI without setup:
|
||||||
//! MAGNOTIA_WHISPER_TEST_MODEL=/path/to/ggml-tiny.bin
|
//! LUMOTIA_WHISPER_TEST_MODEL=/path/to/ggml-tiny.bin
|
||||||
//! MAGNOTIA_WHISPER_TEST_AUDIO=/path/to/jfk.wav
|
//! LUMOTIA_WHISPER_TEST_AUDIO=/path/to/jfk.wav
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn jfk_transcription_benchmark() {
|
fn jfk_transcription_benchmark() {
|
||||||
let Ok(model_path) = env::var("MAGNOTIA_WHISPER_TEST_MODEL") else {
|
let Ok(model_path) = env::var("LUMOTIA_WHISPER_TEST_MODEL") else {
|
||||||
eprintln!("MAGNOTIA_WHISPER_TEST_MODEL not set — skipping");
|
eprintln!("LUMOTIA_WHISPER_TEST_MODEL not set — skipping");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Ok(audio_path) = env::var("MAGNOTIA_WHISPER_TEST_AUDIO") else {
|
let Ok(audio_path) = env::var("LUMOTIA_WHISPER_TEST_AUDIO") else {
|
||||||
eprintln!("MAGNOTIA_WHISPER_TEST_AUDIO not set — skipping");
|
eprintln!("LUMOTIA_WHISPER_TEST_AUDIO not set — skipping");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//! Thread-count scaling sweep for Whisper Tiny.
|
//! Thread-count scaling sweep for Whisper Tiny.
|
||||||
//! Runs the JFK clip at n_threads = 1, 2, 4, 6, 8, 12, prints RTF tables.
|
//! Runs the JFK clip at n_threads = 1, 2, 4, 6, 8, 12, prints RTF tables.
|
||||||
//! Env-gated by `MAGNOTIA_WHISPER_TEST_MODEL` + `MAGNOTIA_WHISPER_TEST_AUDIO`.
|
//! Env-gated by `LUMOTIA_WHISPER_TEST_MODEL` + `LUMOTIA_WHISPER_TEST_AUDIO`.
|
||||||
//!
|
//!
|
||||||
//! Now prints multiple panels driven by `MAGNOTIA_POWER_STATE_OVERRIDE` so
|
//! Now prints multiple panels driven by `LUMOTIA_POWER_STATE_OVERRIDE` so
|
||||||
//! the helper's predicted thread count for each (power, GPU) combination
|
//! the helper's predicted thread count for each (power, GPU) combination
|
||||||
//! can be compared against the empirical RTF data.
|
//! can be compared against the empirical RTF data.
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextPar
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn whisper_thread_count_sweep() {
|
fn whisper_thread_count_sweep() {
|
||||||
let Ok(model_path) = env::var("MAGNOTIA_WHISPER_TEST_MODEL") else {
|
let Ok(model_path) = env::var("LUMOTIA_WHISPER_TEST_MODEL") else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Ok(audio_path) = env::var("MAGNOTIA_WHISPER_TEST_AUDIO") else {
|
let Ok(audio_path) = env::var("LUMOTIA_WHISPER_TEST_AUDIO") else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ fn whisper_thread_count_sweep() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Four panels: CPU and GPU axes for the predicted-helper-pick column,
|
// Four panels: CPU and GPU axes for the predicted-helper-pick column,
|
||||||
// crossed with AC and battery via MAGNOTIA_POWER_STATE_OVERRIDE.
|
// crossed with AC and battery via LUMOTIA_POWER_STATE_OVERRIDE.
|
||||||
let panels = [
|
let panels = [
|
||||||
("AC, CPU", "ac", false),
|
("AC, CPU", "ac", false),
|
||||||
("AC, GPU (Vulkan)", "ac", true),
|
("AC, GPU (Vulkan)", "ac", true),
|
||||||
@@ -80,11 +80,11 @@ fn whisper_thread_count_sweep() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (label, power, gpu_offloaded_for_helper) in panels {
|
for (label, power, gpu_offloaded_for_helper) in panels {
|
||||||
env::set_var("MAGNOTIA_POWER_STATE_OVERRIDE", power);
|
env::set_var("LUMOTIA_POWER_STATE_OVERRIDE", power);
|
||||||
let helper_pick = inference_thread_count(Workload::Whisper, gpu_offloaded_for_helper);
|
let helper_pick = inference_thread_count(Workload::Whisper, gpu_offloaded_for_helper);
|
||||||
run_sweep_panel(label, helper_pick, &ctx, &samples, audio_secs, &targets);
|
run_sweep_panel(label, helper_pick, &ctx, &samples, audio_secs, &targets);
|
||||||
}
|
}
|
||||||
env::remove_var("MAGNOTIA_POWER_STATE_OVERRIDE");
|
env::remove_var("LUMOTIA_POWER_STATE_OVERRIDE");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_sweep_panel(
|
fn run_sweep_panel(
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
//! Smoke test: whisper-rs 0.16 loads a GGUF model, transcribes silence, and
|
//! Smoke test: whisper-rs 0.16 loads a GGUF model, transcribes silence, and
|
||||||
//! accepts set_initial_prompt without panicking.
|
//! accepts set_initial_prompt without panicking.
|
||||||
//!
|
//!
|
||||||
//! Runs only when `MAGNOTIA_WHISPER_TEST_MODEL` is set to the path of a
|
//! Runs only when `LUMOTIA_WHISPER_TEST_MODEL` is set to the path of a
|
||||||
//! ggml/gguf whisper model on disk. Otherwise the test exits quiet.
|
//! ggml/gguf whisper model on disk. Otherwise the test exits quiet.
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn whisper_rs_smoke_loads_and_transcribes() {
|
fn whisper_rs_smoke_loads_and_transcribes() {
|
||||||
let model_path = match env::var("MAGNOTIA_WHISPER_TEST_MODEL") {
|
let model_path = match env::var("LUMOTIA_WHISPER_TEST_MODEL") {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("MAGNOTIA_WHISPER_TEST_MODEL not set — skipping");
|
eprintln!("LUMOTIA_WHISPER_TEST_MODEL not set — skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ pub fn resolve_recording_path(
|
|||||||
/// collisions, which `SystemTime::now()` alone cannot guarantee
|
/// collisions, which `SystemTime::now()` alone cannot guarantee
|
||||||
/// (two calls in the same clock tick can return identical nanos).
|
/// (two calls in the same clock tick can return identical nanos).
|
||||||
///
|
///
|
||||||
/// Format: `magnotia-<secs>-<nanos_in_sec>-<counter>.wav`, e.g.
|
/// Format: `lumotia-<secs>-<nanos_in_sec>-<counter>.wav`, e.g.
|
||||||
/// `magnotia-1776828000-123456789-0000.wav`.
|
/// `lumotia-1776828000-123456789-0000.wav`.
|
||||||
fn recording_filename() -> String {
|
fn recording_filename() -> String {
|
||||||
let duration = std::time::SystemTime::now()
|
let duration = std::time::SystemTime::now()
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
@@ -61,7 +61,7 @@ fn recording_filename() -> String {
|
|||||||
let secs = duration.as_secs();
|
let secs = duration.as_secs();
|
||||||
let nanos = duration.subsec_nanos();
|
let nanos = duration.subsec_nanos();
|
||||||
let counter = RECORDING_COUNTER.fetch_add(1, Ordering::SeqCst);
|
let counter = RECORDING_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||||||
format!("magnotia-{secs}-{nanos:09}-{counter:04}.wav")
|
format!("lumotia-{secs}-{nanos:09}-{counter:04}.wav")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process-lifetime monotonic counter for `recording_filename`. Starts
|
/// Process-lifetime monotonic counter for `recording_filename`. Starts
|
||||||
@@ -97,11 +97,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn recording_filename_has_expected_shape() {
|
fn recording_filename_has_expected_shape() {
|
||||||
let name = recording_filename();
|
let name = recording_filename();
|
||||||
assert!(name.starts_with("magnotia-"));
|
assert!(name.starts_with("lumotia-"));
|
||||||
assert!(name.ends_with(".wav"));
|
assert!(name.ends_with(".wav"));
|
||||||
// Shape: magnotia-<digits>-<9 digits>-<>=4 digits>.wav
|
// Shape: lumotia-<digits>-<9 digits>-<>=4 digits>.wav
|
||||||
let rest = name
|
let rest = name
|
||||||
.strip_prefix("magnotia-")
|
.strip_prefix("lumotia-")
|
||||||
.and_then(|s| s.strip_suffix(".wav"))
|
.and_then(|s| s.strip_suffix(".wav"))
|
||||||
.expect("shape prefix/suffix");
|
.expect("shape prefix/suffix");
|
||||||
let parts: Vec<&str> = rest.split('-').collect();
|
let parts: Vec<&str> = rest.split('-').collect();
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ use crate::commands::security::ensure_main_window;
|
|||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
|
|
||||||
const DEFAULT_RECENT_ERRORS: i64 = 50;
|
const DEFAULT_RECENT_ERRORS: i64 = 50;
|
||||||
const MAGNOTIA_VERSION: &str = env!("CARGO_PKG_VERSION");
|
const LUMOTIA_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
/// Install the Rust panic hook. Writes each panic to a separate file in
|
/// Install the Rust panic hook. Writes each panic to a separate file in
|
||||||
/// crashes_dir so the diagnostic-report bundler can attach them. Also
|
/// crashes_dir so the diagnostic-report bundler can attach them. Also
|
||||||
@@ -60,7 +60,7 @@ pub fn install_panic_hook() {
|
|||||||
\n\
|
\n\
|
||||||
OS: {os} {arch}\n\
|
OS: {os} {arch}\n\
|
||||||
RUST_BACKTRACE: {bt}\n",
|
RUST_BACKTRACE: {bt}\n",
|
||||||
ver = MAGNOTIA_VERSION,
|
ver = LUMOTIA_VERSION,
|
||||||
ts = ts,
|
ts = ts,
|
||||||
thread = std::thread::current().name().unwrap_or("<unnamed>"),
|
thread = std::thread::current().name().unwrap_or("<unnamed>"),
|
||||||
info = info,
|
info = info,
|
||||||
@@ -312,7 +312,7 @@ async fn generate_diagnostic_report_inner(
|
|||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
|
|
||||||
out.push_str("# Magnotia diagnostic report\n\n");
|
out.push_str("# Magnotia diagnostic report\n\n");
|
||||||
out.push_str(&format!("- Version: `{}`\n", MAGNOTIA_VERSION));
|
out.push_str(&format!("- Version: `{}`\n", LUMOTIA_VERSION));
|
||||||
out.push_str(&format!(
|
out.push_str(&format!(
|
||||||
"- OS / arch: `{} / {}`\n",
|
"- OS / arch: `{} / {}`\n",
|
||||||
std::env::consts::OS,
|
std::env::consts::OS,
|
||||||
@@ -527,7 +527,7 @@ pub async fn save_diagnostic_report(
|
|||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
.map(|d| d.as_secs())
|
.map(|d| d.as_secs())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let path = dir.join(format!("magnotia-diagnostic-{ts}.md"));
|
let path = dir.join(format!("lumotia-diagnostic-{ts}.md"));
|
||||||
|
|
||||||
fs::write(&path, &report).map_err(|e| format!("write file: {e}"))?;
|
fs::write(&path, &report).map_err(|e| format!("write file: {e}"))?;
|
||||||
Ok(path.to_string_lossy().to_string())
|
Ok(path.to_string_lossy().to_string())
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn write_text_file_errors_on_bad_parent() {
|
async fn write_text_file_errors_on_bad_parent() {
|
||||||
let result = write_text_file_cmd(
|
let result = write_text_file_cmd(
|
||||||
"/definitely-not-a-real-path-magnotia-phase9/out.md".into(),
|
"/definitely-not-a-real-path-lumotia-phase9/out.md".into(),
|
||||||
"x".into(),
|
"x".into(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
Reference in New Issue
Block a user