diff --git a/crates/audio/src/concurrency.rs b/crates/audio/src/concurrency.rs index be4db54..e0e68fb 100644 --- a/crates/audio/src/concurrency.rs +++ b/crates/audio/src/concurrency.rs @@ -15,5 +15,7 @@ pub async fn decode_and_resample(path: &Path) -> Result { resample_to_16khz(&audio) }) .await - .map_err(|e| magnotia_core::error::MagnotiaError::AudioDecodeFailed(format!("Task join error: {e}")))? + .map_err(|e| { + magnotia_core::error::MagnotiaError::AudioDecodeFailed(format!("Task join error: {e}")) + })? } diff --git a/crates/audio/src/decode.rs b/crates/audio/src/decode.rs index b465028..d4953c9 100644 --- a/crates/audio/src/decode.rs +++ b/crates/audio/src/decode.rs @@ -99,7 +99,9 @@ fn decode_media_stream( .ok_or_else(|| MagnotiaError::AudioDecodeFailed("Unknown sample rate".into()))?; if sample_rate == 0 { - return Err(MagnotiaError::AudioDecodeFailed("Invalid sample rate: 0".into())); + return Err(MagnotiaError::AudioDecodeFailed( + "Invalid sample rate: 0".into(), + )); } let track_id = track.id; @@ -166,7 +168,9 @@ fn decode_media_stream( } if samples.is_empty() { - return Err(MagnotiaError::AudioDecodeFailed("No audio data decoded".into())); + return Err(MagnotiaError::AudioDecodeFailed( + "No audio data decoded".into(), + )); } Ok(AudioSamples::new(samples, sample_rate, 1)) diff --git a/crates/audio/src/streaming_resample.rs b/crates/audio/src/streaming_resample.rs index e84ce06..ac98443 100644 --- a/crates/audio/src/streaming_resample.rs +++ b/crates/audio/src/streaming_resample.rs @@ -77,7 +77,9 @@ impl StreamingResampler { INPUT_CHUNK, 1, // mono ) - .map_err(|e| MagnotiaError::AudioDecodeFailed(format!("StreamingResampler init failed: {e}")))?; + .map_err(|e| { + MagnotiaError::AudioDecodeFailed(format!("StreamingResampler init failed: {e}")) + })?; Ok(Self::Sinc { resampler, @@ -142,7 +144,9 @@ impl StreamingResampler { let input = vec![chunk]; let result = resampler.process(&input, None).map_err(|e| { - MagnotiaError::AudioDecodeFailed(format!("StreamingResampler flush failed: {e}")) + MagnotiaError::AudioDecodeFailed(format!( + "StreamingResampler flush failed: {e}" + )) })?; let Some(mut out) = result.into_iter().next() else { diff --git a/crates/audio/src/wav.rs b/crates/audio/src/wav.rs index 2e3af58..3582037 100644 --- a/crates/audio/src/wav.rs +++ b/crates/audio/src/wav.rs @@ -42,8 +42,9 @@ impl WavWriter { }; let file = std::fs::File::create(path).map_err(MagnotiaError::Io)?; let buffered = BufWriter::new(file); - let inner = hound::WavWriter::new(buffered, spec) - .map_err(|e| MagnotiaError::Io(std::io::Error::other(format!("WAV create failed: {e}"))))?; + let inner = hound::WavWriter::new(buffered, spec).map_err(|e| { + MagnotiaError::Io(std::io::Error::other(format!("WAV create failed: {e}"))) + })?; Ok(Self { inner, samples_since_flush: 0, @@ -76,9 +77,9 @@ impl WavWriter { /// `Self::DEFAULT_FLUSH_EVERY_SAMPLES` — but may do so at natural /// boundaries (end-of-utterance, UI events) for tighter recovery. pub fn flush(&mut self) -> Result<()> { - self.inner - .flush() - .map_err(|e| MagnotiaError::Io(std::io::Error::other(format!("WAV flush failed: {e}"))))?; + self.inner.flush().map_err(|e| { + MagnotiaError::Io(std::io::Error::other(format!("WAV flush failed: {e}"))) + })?; self.samples_since_flush = 0; Ok(()) } @@ -110,14 +111,14 @@ pub fn write_wav(path: &Path, audio: &AudioSamples) -> Result<()> { for &sample in audio.samples() { let clamped = sample.clamp(-1.0, 1.0); let int_sample = (clamped * i16::MAX as f32) as i16; - writer - .write_sample(int_sample) - .map_err(|e| MagnotiaError::Io(std::io::Error::other(format!("WAV write failed: {e}"))))?; + writer.write_sample(int_sample).map_err(|e| { + MagnotiaError::Io(std::io::Error::other(format!("WAV write failed: {e}"))) + })?; } - writer - .finalize() - .map_err(|e| MagnotiaError::Io(std::io::Error::other(format!("WAV finalize failed: {e}"))))?; + writer.finalize().map_err(|e| { + MagnotiaError::Io(std::io::Error::other(format!("WAV finalize failed: {e}"))) + })?; Ok(()) } diff --git a/crates/core/src/paths.rs b/crates/core/src/paths.rs index 2c4f452..2f0ab1f 100644 --- a/crates/core/src/paths.rs +++ b/crates/core/src/paths.rs @@ -91,7 +91,10 @@ fn resolve_app_data_dir() -> PathBuf { return PathBuf::from(xdg).join("magnotia"); } } - PathBuf::from(home).join(".local").join("share").join("magnotia") + PathBuf::from(home) + .join(".local") + .join("share") + .join("magnotia") } #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))] @@ -112,7 +115,10 @@ mod tests { let paths = AppPaths { app_data_dir: PathBuf::from("/tmp/magnotia-test"), }; - assert_eq!(paths.database_path(), PathBuf::from("/tmp/magnotia-test/magnotia.db")); + assert_eq!( + paths.database_path(), + PathBuf::from("/tmp/magnotia-test/magnotia.db") + ); assert_eq!( paths.speech_model_dir(&ModelId::new("whisper-base-en")), PathBuf::from("/tmp/magnotia-test/models/whisper-base-en") diff --git a/crates/core/src/power.rs b/crates/core/src/power.rs index 44e5d7b..3945c8d 100644 --- a/crates/core/src/power.rs +++ b/crates/core/src/power.rs @@ -162,7 +162,9 @@ static TEST_OVERRIDE: Mutex> = Mutex::new(None); #[cfg(test)] fn test_get_override() -> Option { - *TEST_OVERRIDE.lock().expect("power test override mutex poisoned") + *TEST_OVERRIDE + .lock() + .expect("power test override mutex poisoned") } /// Drop-guard that resets `TEST_OVERRIDE` to `None` on drop (including on unwind). @@ -174,7 +176,9 @@ struct OverrideGuard; #[cfg(test)] impl Drop for OverrideGuard { fn drop(&mut self) { - *TEST_OVERRIDE.lock().expect("power test override mutex poisoned") = None; + *TEST_OVERRIDE + .lock() + .expect("power test override mutex poisoned") = None; } } @@ -188,7 +192,9 @@ impl Drop for OverrideGuard { pub(crate) fn with_override(state: Option, body: impl FnOnce() -> R) -> R { static TEST_LOCK: Mutex<()> = Mutex::new(()); let _lock = TEST_LOCK.lock().expect("power TEST_LOCK poisoned"); - *TEST_OVERRIDE.lock().expect("power test override mutex poisoned") = state; + *TEST_OVERRIDE + .lock() + .expect("power test override mutex poisoned") = state; let _guard = OverrideGuard; body() } @@ -226,7 +232,10 @@ mod tests { let dir = tempdir().unwrap(); write_supply(dir.path(), "AC", "Mains", "0"); write_supply(dir.path(), "BAT0", "Battery", "0"); - assert_eq!(parse_power_state_from_dir(dir.path()), PowerState::OnBattery); + assert_eq!( + parse_power_state_from_dir(dir.path()), + PowerState::OnBattery + ); } #[test] diff --git a/crates/core/src/process_watch.rs b/crates/core/src/process_watch.rs index 7a93552..0bed974 100644 --- a/crates/core/src/process_watch.rs +++ b/crates/core/src/process_watch.rs @@ -39,8 +39,7 @@ impl ProcessLister { /// Refresh the process table in place and return the current /// lowercased executable names. pub fn snapshot(&mut self) -> Vec { - self.system - .refresh_processes(ProcessesToUpdate::All, true); + self.system.refresh_processes(ProcessesToUpdate::All, true); self.system .processes() .values() diff --git a/crates/core/src/tuning.rs b/crates/core/src/tuning.rs index c3a2417..45c0e36 100644 --- a/crates/core/src/tuning.rs +++ b/crates/core/src/tuning.rs @@ -113,7 +113,9 @@ mod tests { fn with_thread_env_lock(body: impl FnOnce() -> R) -> R { use std::sync::Mutex; static THREAD_ENV_LOCK: Mutex<()> = Mutex::new(()); - let _lock = THREAD_ENV_LOCK.lock().expect("tuning thread-env lock poisoned"); + let _lock = THREAD_ENV_LOCK + .lock() + .expect("tuning thread-env lock poisoned"); body() } @@ -126,8 +128,10 @@ mod tests { with_thread_env_lock(|| { std::env::remove_var("MAGNOTIA_INFERENCE_THREADS"); let n = inference_thread_count(Workload::Llm, false); - assert!(n >= MIN_INFERENCE_THREADS && n <= MAX_INFERENCE_THREADS, - "got {n}, expected within [{MIN_INFERENCE_THREADS}, {MAX_INFERENCE_THREADS}]"); + assert!( + (MIN_INFERENCE_THREADS..=MAX_INFERENCE_THREADS).contains(&n), + "got {n}, expected within [{MIN_INFERENCE_THREADS}, {MAX_INFERENCE_THREADS}]" + ); }); } @@ -175,8 +179,10 @@ mod tests { std::env::remove_var("MAGNOTIA_INFERENCE_THREADS"); crate::power::with_override(Some(PowerState::OnAc), || { let n = inference_thread_count(Workload::Llm, true); - assert!(n <= GPU_FLOOR_LLM.max(MIN_INFERENCE_THREADS), - "Llm with GPU offload should clamp to {GPU_FLOOR_LLM}, got {n}"); + assert!( + n <= GPU_FLOOR_LLM.max(MIN_INFERENCE_THREADS), + "Llm with GPU offload should clamp to {GPU_FLOOR_LLM}, got {n}" + ); assert!(n >= MIN_INFERENCE_THREADS); }); }); @@ -196,11 +202,12 @@ mod tests { }); } + const _: () = assert!(GPU_FLOOR_WHISPER >= GPU_FLOOR_LLM); + #[test] fn whisper_gpu_floor_is_at_least_llm_gpu_floor() { // Architectural invariant: whisper retains CPU work even when // GPU-offloaded; its floor must not be lower than the LLM's. - assert!(GPU_FLOOR_WHISPER >= GPU_FLOOR_LLM); } #[test] diff --git a/crates/llm/src/lib.rs b/crates/llm/src/lib.rs index 8f7ea23..1453ab9 100644 --- a/crates/llm/src/lib.rs +++ b/crates/llm/src/lib.rs @@ -172,8 +172,8 @@ impl LlmEngine { // follow-up in docs/superpowers/specs/2026-05-09-battery-gpu-aware- // thread-tuning-design.md (§ Out of scope). let gpu_offloaded = use_gpu && gpu_layers >= model.n_layer(); - let thread_count = i32::try_from(inference_thread_count(Workload::Llm, gpu_offloaded)) - .unwrap_or(4); + let thread_count = + i32::try_from(inference_thread_count(Workload::Llm, gpu_offloaded)).unwrap_or(4); let ctx_params = LlamaContextParams::default() .with_n_ctx(Some( NonZeroU32::new(n_ctx).expect("n_ctx must be non-zero"), diff --git a/crates/storage/src/database.rs b/crates/storage/src/database.rs index 8f61a4a..3858965 100644 --- a/crates/storage/src/database.rs +++ b/crates/storage/src/database.rs @@ -182,7 +182,9 @@ pub async fn update_transcript( .bind(id) .execute(pool) .await - .map_err(|e| MagnotiaError::StorageError(format!("Update transcript failed: {e}")))?; + .map_err(|e| { + MagnotiaError::StorageError(format!("Update transcript failed: {e}")) + })?; Ok(res.rows_affected()) } (Some(t), None) => { @@ -191,7 +193,9 @@ pub async fn update_transcript( .bind(id) .execute(pool) .await - .map_err(|e| MagnotiaError::StorageError(format!("Update transcript failed: {e}")))?; + .map_err(|e| { + MagnotiaError::StorageError(format!("Update transcript failed: {e}")) + })?; Ok(res.rows_affected()) } (None, Some(ttl)) => { @@ -200,7 +204,9 @@ pub async fn update_transcript( .bind(id) .execute(pool) .await - .map_err(|e| MagnotiaError::StorageError(format!("Update transcript failed: {e}")))?; + .map_err(|e| { + MagnotiaError::StorageError(format!("Update transcript failed: {e}")) + })?; Ok(res.rows_affected()) } (None, None) => Ok(0), @@ -484,7 +490,9 @@ pub async fn complete_subtask_and_check_parent(pool: &SqlitePool, subtask_id: &s .bind(&pid) .execute(&mut *tx) .await - .map_err(|e| MagnotiaError::StorageError(format!("Auto-complete parent failed: {e}")))?; + .map_err(|e| { + MagnotiaError::StorageError(format!("Auto-complete parent failed: {e}")) + })?; } } @@ -708,7 +716,9 @@ pub async fn set_implementation_rule_enabled( .bind(id) .execute(pool) .await - .map_err(|e| MagnotiaError::StorageError(format!("Set implementation rule enabled failed: {e}")))?; + .map_err(|e| { + MagnotiaError::StorageError(format!("Set implementation rule enabled failed: {e}")) + })?; get_implementation_rule(pool, id).await?.ok_or_else(|| { MagnotiaError::StorageError(format!( @@ -731,7 +741,9 @@ pub async fn mark_implementation_rule_fired( .bind(id) .execute(pool) .await - .map_err(|e| MagnotiaError::StorageError(format!("Mark implementation rule fired failed: {e}")))?; + .map_err(|e| { + MagnotiaError::StorageError(format!("Mark implementation rule fired failed: {e}")) + })?; get_implementation_rule(pool, id).await?.ok_or_else(|| { MagnotiaError::StorageError(format!( @@ -745,7 +757,9 @@ pub async fn delete_implementation_rule(pool: &SqlitePool, id: &str) -> Result<( .bind(id) .execute(pool) .await - .map_err(|e| MagnotiaError::StorageError(format!("Delete implementation rule failed: {e}")))?; + .map_err(|e| { + MagnotiaError::StorageError(format!("Delete implementation rule failed: {e}")) + })?; Ok(()) } @@ -2511,24 +2525,21 @@ mod tests { let removed = prune_error_log(&pool, 90).await.unwrap(); assert_eq!(removed, 1, "only the 200-day row should be pruned"); - let remaining: Vec = sqlx::query_scalar( - "SELECT context FROM error_log ORDER BY id ASC", - ) - .fetch_all(&pool) - .await - .unwrap(); + let remaining: Vec = + sqlx::query_scalar("SELECT context FROM error_log ORDER BY id ASC") + .fetch_all(&pool) + .await + .unwrap(); assert_eq!(remaining, vec!["recent".to_string(), "older".to_string()]); // A 14-day window prunes the 30-day row too. let removed = prune_error_log(&pool, 14).await.unwrap(); assert_eq!(removed, 1); - let remaining: Vec = sqlx::query_scalar( - "SELECT context FROM error_log", - ) - .fetch_all(&pool) - .await - .unwrap(); + let remaining: Vec = sqlx::query_scalar("SELECT context FROM error_log") + .fetch_all(&pool) + .await + .unwrap(); assert_eq!(remaining, vec!["recent".to_string()]); } } diff --git a/crates/storage/src/lib.rs b/crates/storage/src/lib.rs index 214b1d1..557a7db 100644 --- a/crates/storage/src/lib.rs +++ b/crates/storage/src/lib.rs @@ -15,8 +15,7 @@ pub use database::{ list_profiles, list_recent_completions, list_recent_errors, list_subtasks, list_tasks, list_transcripts, list_transcripts_paged, log_error, mark_implementation_rule_fired, prune_error_log, record_feedback, search_transcripts, set_implementation_rule_enabled, - set_setting, - set_task_energy, uncomplete_task, update_profile, update_task, update_transcript, + set_setting, set_task_energy, uncomplete_task, update_profile, update_task, update_transcript, update_transcript_meta, DailyCompletionCount, ErrorLogRow, FeedbackRow, FeedbackTargetType, ImplementationRuleRow, InsertTranscriptParams, ProfileRow, ProfileTermRow, RecordFeedbackParams, TaskRow, TranscriptRow, diff --git a/crates/storage/src/migrations.rs b/crates/storage/src/migrations.rs index 5556080..5b114a1 100644 --- a/crates/storage/src/migrations.rs +++ b/crates/storage/src/migrations.rs @@ -553,7 +553,9 @@ async fn run_migrations_slice(pool: &SqlitePool, migrations: &[(i64, &str, &str) ) .execute(pool) .await - .map_err(|e| MagnotiaError::StorageError(format!("Schema version table creation failed: {e}")))?; + .map_err(|e| { + MagnotiaError::StorageError(format!("Schema version table creation failed: {e}")) + })?; let current: i64 = sqlx::query_scalar("SELECT COALESCE(MAX(version), 0) FROM schema_version") .fetch_one(pool) @@ -1178,7 +1180,8 @@ mod tests { .map(|r| r.get::("detail")) .collect(); assert!( - plan.iter().any(|row| row.contains("idx_transcripts_profile_created")), + plan.iter() + .any(|row| row.contains("idx_transcripts_profile_created")), "planner should use the composite index, got plan: {plan:?}", ); } diff --git a/crates/transcription/src/model_manager.rs b/crates/transcription/src/model_manager.rs index fb3416e..aaafcb2 100644 --- a/crates/transcription/src/model_manager.rs +++ b/crates/transcription/src/model_manager.rs @@ -116,7 +116,10 @@ fn verified_manifest_path(dir: &Path) -> PathBuf { dir.join(".magnotia-verified") } -fn verified_manifest_matches(entry: &magnotia_core::model_registry::ModelEntry, dir: &Path) -> bool { +fn verified_manifest_matches( + entry: &magnotia_core::model_registry::ModelEntry, + dir: &Path, +) -> bool { let manifest = match std::fs::read_to_string(verified_manifest_path(dir)) { Ok(contents) => contents, Err(_) => return false, diff --git a/crates/transcription/src/orchestrator.rs b/crates/transcription/src/orchestrator.rs index 6bbfe7c..3eabc58 100644 --- a/crates/transcription/src/orchestrator.rs +++ b/crates/transcription/src/orchestrator.rs @@ -70,9 +70,7 @@ impl TranscriptionProvider for LocalProviderAdapter { .map(|c| c.sample_rate) .unwrap_or(magnotia_core::constants::WHISPER_SAMPLE_RATE), channels: local.map(|c| c.channels).unwrap_or(1), - initial_prompt_supported: local - .map(|c| c.supports_initial_prompt) - .unwrap_or(false), + initial_prompt_supported: local.map(|c| c.supports_initial_prompt).unwrap_or(false), language_hint_supported: true, streaming_supported: false, cost_class: CostClass::Free, diff --git a/crates/transcription/src/whisper_rs_backend.rs b/crates/transcription/src/whisper_rs_backend.rs index 3feae74..bed4b04 100644 --- a/crates/transcription/src/whisper_rs_backend.rs +++ b/crates/transcription/src/whisper_rs_backend.rs @@ -65,7 +65,9 @@ impl Transcriber for WhisperRsBackend { ); let mut state = self.ctx.create_state().map_err(|e| { - MagnotiaError::TranscriptionFailed(WhisperBackendError::State(e.to_string()).to_string()) + MagnotiaError::TranscriptionFailed( + WhisperBackendError::State(e.to_string()).to_string(), + ) })?; let mut params = FullParams::new(SamplingStrategy::Greedy { best_of: 1 }); diff --git a/crates/transcription/tests/jfk_bench.rs b/crates/transcription/tests/jfk_bench.rs index 55ccd3c..3470a8f 100644 --- a/crates/transcription/tests/jfk_bench.rs +++ b/crates/transcription/tests/jfk_bench.rs @@ -30,7 +30,10 @@ fn jfk_transcription_benchmark() { let sample_rate = u32::from_le_bytes(bytes[24..28].try_into().unwrap()); let channels = u16::from_le_bytes(bytes[22..24].try_into().unwrap()); let bits = u16::from_le_bytes(bytes[34..36].try_into().unwrap()); - eprintln!("[bench] wav spec: {} Hz, {} ch, {}-bit", sample_rate, channels, bits); + eprintln!( + "[bench] wav spec: {} Hz, {} ch, {}-bit", + sample_rate, channels, bits + ); assert_eq!(sample_rate, 16_000, "expected 16 kHz wav"); assert_eq!(channels, 1, "expected mono"); assert_eq!(bits, 16, "expected 16-bit PCM"); @@ -48,7 +51,10 @@ fn jfk_transcription_benchmark() { ); let rss_before_load_kb = read_rss_kb(); - eprintln!("[bench] RSS before model load: {} MB", rss_before_load_kb / 1024); + eprintln!( + "[bench] RSS before model load: {} MB", + rss_before_load_kb / 1024 + ); let load_start = Instant::now(); let ctx = WhisperContext::new_with_params(&model_path, WhisperContextParameters::default()) @@ -57,9 +63,11 @@ fn jfk_transcription_benchmark() { eprintln!("[bench] model load: {:.2}s", load_dur.as_secs_f64()); let rss_after_load_kb = read_rss_kb(); - eprintln!("[bench] RSS after model load: {} MB (delta +{} MB)", + eprintln!( + "[bench] RSS after model load: {} MB (delta +{} MB)", rss_after_load_kb / 1024, - (rss_after_load_kb.saturating_sub(rss_before_load_kb)) / 1024); + (rss_after_load_kb.saturating_sub(rss_before_load_kb)) / 1024 + ); let mut state = ctx.create_state().expect("whisper state"); let mut params = FullParams::new(SamplingStrategy::Greedy { best_of: 1 }); @@ -110,12 +118,20 @@ fn jfk_transcription_benchmark() { let rss_final_kb = read_rss_kb(); eprintln!("[bench] RSS final: {} MB", rss_final_kb / 1024); - eprintln!(""); + eprintln!(); eprintln!("=== SUMMARY ==="); eprintln!("audio: {:.2}s", audio_secs); eprintln!("model_load: {:.2}s", load_dur.as_secs_f64()); - eprintln!("cold xc: {:.2}s RTF={:.3}", cold_dur.as_secs_f64(), cold_dur.as_secs_f64() / audio_secs); - eprintln!("warm xc: {:.2}s RTF={:.3}", warm_dur.as_secs_f64(), warm_dur.as_secs_f64() / audio_secs); + eprintln!( + "cold xc: {:.2}s RTF={:.3}", + cold_dur.as_secs_f64(), + cold_dur.as_secs_f64() / audio_secs + ); + eprintln!( + "warm xc: {:.2}s RTF={:.3}", + warm_dur.as_secs_f64(), + warm_dur.as_secs_f64() / audio_secs + ); eprintln!("RSS peak: {} MB", rss_final_kb / 1024); } @@ -124,7 +140,9 @@ fn read_rss_kb() -> u64 { let s = std::fs::read_to_string(format!("/proc/{pid}/status")).unwrap_or_default(); for line in s.lines() { if let Some(rest) = line.strip_prefix("VmRSS:") { - return rest.trim().split_whitespace().next() + return rest + .split_whitespace() + .next() .and_then(|n| n.parse::().ok()) .unwrap_or(0); } diff --git a/crates/transcription/tests/thread_sweep.rs b/crates/transcription/tests/thread_sweep.rs index 6ac7df0..81578a1 100644 --- a/crates/transcription/tests/thread_sweep.rs +++ b/crates/transcription/tests/thread_sweep.rs @@ -82,14 +82,7 @@ fn whisper_thread_count_sweep() { for (label, power, gpu_offloaded_for_helper) in panels { env::set_var("MAGNOTIA_POWER_STATE_OVERRIDE", power); 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"); } @@ -102,10 +95,8 @@ fn run_sweep_panel( audio_secs: f64, targets: &[i32], ) { - eprintln!(""); - eprintln!( - "=== n_threads scaling: {label} (helper picks: {helper_pick}) ===" - ); + eprintln!(); + eprintln!("=== n_threads scaling: {label} (helper picks: {helper_pick}) ==="); eprintln!("n_threads | xc_time | RTF | speedup_vs_1"); eprintln!("----------|---------|--------|-------------"); let mut baseline_dur: Option = None; diff --git a/docs/superpowers/audits/2026-05-10-phase10a-stabilization-gate.md b/docs/superpowers/audits/2026-05-10-phase10a-stabilization-gate.md new file mode 100644 index 0000000..9220910 --- /dev/null +++ b/docs/superpowers/audits/2026-05-10-phase10a-stabilization-gate.md @@ -0,0 +1,91 @@ +--- +name: Phase 10a stabilization gate after post-handover commits +description: Current-head stabilization checkpoint before resuming Phase 10a QC/dogfood. Covers the two commits ahead of origin/main, verification results, and scope decision for dormant Phase A orchestrator work. +type: audit +tags: [phase10a, stabilization, release, orchestrator, verification] +created: 2026/05/10 +status: green-with-manual-qc-remaining +author: Hermes Agent on behalf of Jake Sames +--- + +# Phase 10a — Stabilization Gate + +## Scope + +This checkpoint updates the 2026/04/25 handover and static Phase 10a audit for the current local `main`, which is two commits ahead of `origin/main`. + +Current local-only commits inspected: + +- `c95a5da` — `docs(roadmap): bookmark SIE + adjacent embeddings/rerank/extract servers for PKM phase` +- `6bc8acc` — `feat(transcription): Phase A — engine protocol + registry + orchestrator (clean-room)` + +## Findings + +### PKM roadmap bookmark + +Low release risk. The SIE / embeddings / rerank / extraction note is documentation-only and explicitly marked deferred. It should not affect v0.1 runtime or QA scope. + +### Phase A transcription orchestrator + +Medium architectural scope, low immediate runtime risk. + +The commit adds: + +- `crates/cloud-providers/src/provider.rs` +- `crates/transcription/src/registry.rs` +- `crates/transcription/src/orchestrator.rs` +- wiring exports/dependencies plus `KNOWN-ISSUES.md` KI-06 + +The implementation is deliberately dormant for current app paths. Existing `transcribe_file`, live transcription, and meeting flows still call the existing local engine path directly. KI-06 documents the required follow-up: build the registry at app boot, inject `Arc` into `AppState`, and migrate command call sites through the orchestrator with mock-provider coverage. + +Decision for v0.1 release flow: keep the Phase A commit only if the dormant boundary remains green; do not expand scope into Phase A.1 before Phase 10a unless a direct release blocker requires it. + +## Verification run + +Command run from repo root: + +```bash +cargo fmt --check && \ + cargo clippy --workspace --all-targets -- -D warnings && \ + cargo test --workspace && \ + npm run check && \ + npm run build +``` + +Final result: PASS. + +Notes: + +- Initial run failed `cargo fmt --check`; `cargo fmt` was applied. +- Current Rust/Clippy toolchain also surfaced a few warning-as-error issues unrelated to the new orchestrator surface: + - `manual_range_contains` in `crates/core/src/tuning.rs` + - `assertions_on_constants` in `crates/core/src/tuning.rs` + - `println_empty_string` in transcription benchmark tests + - `trim_split_whitespace` in transcription benchmark helper +- Those were fixed minimally to restore `-D warnings` cleanliness. + +## Files changed by stabilization + +Rust formatting touched multiple existing files. Semantic clippy fixes were limited to: + +- `crates/core/src/tuning.rs` +- `crates/transcription/tests/jfk_bench.rs` +- `crates/transcription/tests/thread_sweep.rs` + +This audit file records why those changes exist. + +## Recommendation + +Resume the original Phase 10a plan now, with this added gate satisfied: + +1. Current HEAD is green. +2. Post-handover commits are inspected. +3. Phase A orchestrator work is classified as dormant / post-v0.1 follow-up, not a reason to expand release scope. + +Next work remains the manual/runtime Phase 10a checklist: + +- Dogfood walkthrough from `HANDOVER.md` +- Runtime keyboard / focus / contrast / reduced-motion checks +- RB-08 macOS power-assertion verification by Rachmann +- Clean-install test once release artefacts are available +- Manual GitHub Actions build workflow before tagging v0.1.0 diff --git a/src-tauri/src/commands/feedback.rs b/src-tauri/src/commands/feedback.rs index d99cb27..e3de86f 100644 --- a/src-tauri/src/commands/feedback.rs +++ b/src-tauri/src/commands/feedback.rs @@ -59,4 +59,3 @@ pub async fn record_feedback( .await .map_err(|e| e.to_string()) } - diff --git a/src-tauri/src/commands/live.rs b/src-tauri/src/commands/live.rs index d910dab..614e0b5 100644 --- a/src-tauri/src/commands/live.rs +++ b/src-tauri/src/commands/live.rs @@ -1677,7 +1677,10 @@ mod tests { &message, ); - assert!(!delivered, "send must report not delivered when result_channel errors"); + assert!( + !delivered, + "send must report not delivered when result_channel errors" + ); assert!(result_listener_lost, "result_listener_lost must be set"); assert!( stop_flag.load(Ordering::Relaxed), diff --git a/src-tauri/src/commands/models.rs b/src-tauri/src/commands/models.rs index a23b9b6..e655511 100644 --- a/src-tauri/src/commands/models.rs +++ b/src-tauri/src/commands/models.rs @@ -319,7 +319,6 @@ pub struct LanguageSupportInfo { pub language_count: u16, } - /// Compile-time target signalling used by `compose_accelerators`. /// Split out so the pure-function behaviour is testable without `cfg!` /// appearing in the test matrix. diff --git a/src-tauri/src/commands/transcription.rs b/src-tauri/src/commands/transcription.rs index d64cb13..2b06a50 100644 --- a/src-tauri/src/commands/transcription.rs +++ b/src-tauri/src/commands/transcription.rs @@ -249,4 +249,3 @@ pub async fn transcribe_file( "raw_text": raw_text, })) } - diff --git a/src-tauri/src/commands/update.rs b/src-tauri/src/commands/update.rs index 1b33867..0365d6d 100644 --- a/src-tauri/src/commands/update.rs +++ b/src-tauri/src/commands/update.rs @@ -7,4 +7,3 @@ pub async fn check_for_update(window: tauri::WebviewWindow) -> Result