agent: lumotia — pin rust toolchain + workspace clippy/fmt sweep
rust-toolchain.toml pins to stable 1.94.1 so contributors and CI runners share the exact rustc / rustfmt / clippy versions. Without the pin, every machine surfaces a different lint set depending on its local install — six pre-existing lints showed up on 1.94.1 that 1.93-era HANDOVER reported clean. Clippy fixes (all pre-existing, not introduced by feature work): - crates/storage/src/database.rs: std::iter::repeat().take() -> repeat_n() - crates/llm/src/lib.rs (docs): "+ frontends" was parsed as a markdown bullet continuation by rustdoc, breaking doc-lazy-continuation. Reworded to "and". - crates/llm/src/lib.rs (loop): while-let-on-iterator -> for-loop. - src-tauri/src/commands/security.rs: .iter().any(|a| *a == x) -> .contains(&x). - src-tauri/src/lib.rs: io::Error::new(Other, e) -> io::Error::other(e). - src-tauri/src/tauri_app_data_migration.rs: drop function-tail `return`s inside cfg blocks; each platform's block now ends with a tail expression. cargo fmt sweep across the workspace. Mechanical layout-only changes; no semantics affected. Workspace gates after this commit: - cargo fmt --check: clean - cargo clippy --workspace --all-targets -- -D warnings: clean - cargo test --workspace: 405/0 (will become 409/0 with Phase A.1+A.2)
This commit is contained in:
@@ -16,8 +16,7 @@ pub(crate) const MAX_CLIPBOARD_BYTES: usize = 1024 * 1024;
|
||||
/// buttons; mirror the secondary-windows capability grant in
|
||||
/// `src-tauri/capabilities/secondary-windows.json` so the IPC trust
|
||||
/// boundary and the permission set stay in lock-step.
|
||||
const CLIPBOARD_ALLOWED_WINDOWS: &[&str] =
|
||||
&["main", "transcript-viewer", "transcription-preview"];
|
||||
const CLIPBOARD_ALLOWED_WINDOWS: &[&str] = &["main", "transcript-viewer", "transcription-preview"];
|
||||
|
||||
/// Copy text to the system clipboard via arboard. Restricted to the
|
||||
/// documented "clipboard-capable" windows (main + transcript-viewer +
|
||||
|
||||
@@ -88,9 +88,12 @@ pub(crate) fn resolve_export_path(path: &Path, bases: &[PathBuf]) -> Result<Path
|
||||
path.display()
|
||||
)
|
||||
})?;
|
||||
let file_name = path
|
||||
.file_name()
|
||||
.ok_or_else(|| format!("Refusing to write {}: path has no filename.", path.display()))?;
|
||||
let file_name = path.file_name().ok_or_else(|| {
|
||||
format!(
|
||||
"Refusing to write {}: path has no filename.",
|
||||
path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
let canon_parent = std::fs::canonicalize(parent).map_err(|e| {
|
||||
format!(
|
||||
|
||||
@@ -427,9 +427,7 @@ impl LiveSessionRuntime {
|
||||
// the dimensions are real. Validation-window drops can fire
|
||||
// before any chunk reaches `process_audio_chunk`; they get
|
||||
// attributed at the next reconciliation once we know the rate.
|
||||
if self.state.last_chunk_sample_rate == 0
|
||||
|| self.state.last_chunk_samples_per_chan == 0
|
||||
{
|
||||
if self.state.last_chunk_sample_rate == 0 || self.state.last_chunk_samples_per_chan == 0 {
|
||||
// Roll back the consumed delta so we re-observe it once
|
||||
// we have dimensions to convert it with.
|
||||
self.state.last_dropped_chunks = self.state.last_dropped_chunks.saturating_sub(delta);
|
||||
@@ -1111,11 +1109,8 @@ fn maybe_dispatch_chunk(
|
||||
let parent_span = tracing::Span::current();
|
||||
thread::spawn(move || {
|
||||
let _parent = parent_span.enter();
|
||||
let inference_span = tracing::info_span!(
|
||||
"inference",
|
||||
chunk_id = current_chunk_id,
|
||||
duration_secs,
|
||||
);
|
||||
let inference_span =
|
||||
tracing::info_span!("inference", chunk_id = current_chunk_id, duration_secs,);
|
||||
let _enter = inference_span.enter();
|
||||
let audio = AudioSamples::mono_16khz(chunk_samples);
|
||||
let started = Instant::now();
|
||||
|
||||
@@ -21,15 +21,12 @@ pub fn ensure_main_window_label(label: &str) -> Result<(), String> {
|
||||
/// `&[&'static str]` and should mirror an entry in
|
||||
/// `src-tauri/capabilities/*.json` — keeping the IPC trust boundary and the
|
||||
/// permission grant in lock-step.
|
||||
pub fn ensure_window_in_set(
|
||||
window: &tauri::WebviewWindow,
|
||||
allowed: &[&str],
|
||||
) -> Result<(), String> {
|
||||
pub fn ensure_window_in_set(window: &tauri::WebviewWindow, allowed: &[&str]) -> Result<(), String> {
|
||||
ensure_window_in_set_label(window.label(), allowed)
|
||||
}
|
||||
|
||||
pub fn ensure_window_in_set_label(label: &str, allowed: &[&str]) -> Result<(), String> {
|
||||
if allowed.iter().any(|a| *a == label) {
|
||||
if allowed.contains(&label) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!(
|
||||
|
||||
@@ -50,10 +50,7 @@ const MAX_TRANSCRIBE_BYTES: u64 = 1024 * 1024 * 1024;
|
||||
/// rejects most obvious attacks), then size (one stat call), then
|
||||
/// path canonicalisation (slowest, only meaningful once the cheaper
|
||||
/// gates pass).
|
||||
pub(crate) fn validate_transcribe_input(
|
||||
path: &Path,
|
||||
metadata_len: u64,
|
||||
) -> Result<(), String> {
|
||||
pub(crate) fn validate_transcribe_input(path: &Path, metadata_len: u64) -> Result<(), String> {
|
||||
let ext = path
|
||||
.extension()
|
||||
.and_then(|s| s.to_str())
|
||||
@@ -67,7 +64,10 @@ pub(crate) fn validate_transcribe_input(
|
||||
)
|
||||
})?;
|
||||
|
||||
if !ALLOWED_AUDIO_EXTENSIONS.iter().any(|allowed| *allowed == ext) {
|
||||
if !ALLOWED_AUDIO_EXTENSIONS
|
||||
.iter()
|
||||
.any(|allowed| *allowed == ext)
|
||||
{
|
||||
return Err(format!(
|
||||
"Refusing to transcribe {}: extension '.{}' is not in the \
|
||||
allowlist. Supported: {}.",
|
||||
@@ -237,8 +237,7 @@ pub async fn transcribe_file(
|
||||
// Trust-5: extension + size gate before we hand the path to the
|
||||
// audio decoder. `std::fs::metadata` resolves symlinks so the size
|
||||
// check sees the actual blob, not a symlink-target lie.
|
||||
let metadata = std::fs::metadata(&path)
|
||||
.map_err(|e| format!("Cannot stat {path}: {e}"))?;
|
||||
let metadata = std::fs::metadata(&path).map_err(|e| format!("Cannot stat {path}: {e}"))?;
|
||||
validate_transcribe_input(Path::new(&path), metadata.len())?;
|
||||
|
||||
let resolved_profile_id =
|
||||
@@ -347,7 +346,9 @@ mod tests_trust5 {
|
||||
|
||||
#[test]
|
||||
fn accepts_each_allowed_extension() {
|
||||
for ext in ["wav", "mp3", "m4a", "mp4", "flac", "ogg", "opus", "webm", "aac"] {
|
||||
for ext in [
|
||||
"wav", "mp3", "m4a", "mp4", "flac", "ogg", "opus", "webm", "aac",
|
||||
] {
|
||||
let path_string = format!("/tmp/clip.{ext}");
|
||||
let path = Path::new(&path_string);
|
||||
assert!(
|
||||
@@ -376,10 +377,8 @@ mod tests_trust5 {
|
||||
|
||||
#[test]
|
||||
fn rejects_oversize_file() {
|
||||
let result = validate_transcribe_input(
|
||||
Path::new("/tmp/huge.wav"),
|
||||
MAX_TRANSCRIBE_BYTES + 1,
|
||||
);
|
||||
let result =
|
||||
validate_transcribe_input(Path::new("/tmp/huge.wav"), MAX_TRANSCRIBE_BYTES + 1);
|
||||
let err = result.expect_err("must reject oversize file");
|
||||
assert!(err.contains("1 GiB"), "unexpected error: {err}");
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ use lumotia_storage::{
|
||||
delete_transcript as db_delete_transcript, get_transcript as db_get_transcript,
|
||||
insert_transcript as db_insert_transcript, list_transcripts_paged,
|
||||
list_trashed_transcripts as db_list_trashed_transcripts,
|
||||
restore_transcript as db_restore_transcript,
|
||||
search_transcripts as db_search_transcripts, update_transcript as db_update_transcript,
|
||||
update_transcript_meta as db_update_transcript_meta, InsertTranscriptParams, TranscriptRow,
|
||||
restore_transcript as db_restore_transcript, search_transcripts as db_search_transcripts,
|
||||
update_transcript as db_update_transcript, update_transcript_meta as db_update_transcript_meta,
|
||||
InsertTranscriptParams, TranscriptRow,
|
||||
};
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
@@ -18,9 +18,7 @@ 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,
|
||||
};
|
||||
use lumotia_core::paths::{check_target_ambiguity, migrate_legacy_data_dir, MigrationStatus};
|
||||
use lumotia_core::types::EngineName;
|
||||
use lumotia_llm::LlmEngine;
|
||||
use lumotia_storage::{
|
||||
@@ -239,7 +237,7 @@ fn build_rolling_appender(logs_dir: &Path) -> std::io::Result<RollingFileAppende
|
||||
.filename_suffix("log")
|
||||
.max_log_files(7)
|
||||
.build(logs_dir)
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))
|
||||
.map_err(std::io::Error::other)
|
||||
}
|
||||
|
||||
/// Install a `tracing` subscriber that writes to stderr (developer
|
||||
@@ -278,9 +276,7 @@ pub fn install_subscriber(logs_dir: &Path) -> Option<WorkerGuard> {
|
||||
// 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();
|
||||
let _ = tracing_subscriber::registry().with(stderr_layer).try_init();
|
||||
eprintln!(
|
||||
"lumotia: failed to install rolling file log appender at {}: {e}",
|
||||
logs_dir.display()
|
||||
|
||||
@@ -41,16 +41,10 @@ pub enum AppDataMigrationStatus {
|
||||
/// after the first successful migration (we preserve legacy as a
|
||||
/// backup), so the warning is informational rather than an
|
||||
/// indication of trouble.
|
||||
BothExistLegacyPreserved {
|
||||
old: PathBuf,
|
||||
new: PathBuf,
|
||||
},
|
||||
BothExistLegacyPreserved { old: PathBuf, new: PathBuf },
|
||||
/// Migration succeeded: legacy copied to new path via atomic
|
||||
/// staging rename, legacy preserved as a backup.
|
||||
Migrated {
|
||||
old: PathBuf,
|
||||
new: PathBuf,
|
||||
},
|
||||
Migrated { old: PathBuf, new: PathBuf },
|
||||
}
|
||||
|
||||
/// Resolve the OLD Tauri `app_data_dir` from platform conventions. The
|
||||
@@ -67,6 +61,10 @@ pub fn legacy_tauri_app_data_dir() -> Option<PathBuf> {
|
||||
}
|
||||
|
||||
fn legacy_tauri_app_data_dir_for(identifier: &str) -> Option<PathBuf> {
|
||||
// Exactly one of the four cfg blocks below is present per target
|
||||
// compile. Each is a tail expression that becomes the function's
|
||||
// return value. Avoiding explicit `return` keeps clippy's
|
||||
// needless_return lint happy on every platform.
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
// XDG_DATA_HOME wins when set and non-empty, per the XDG Base
|
||||
@@ -79,29 +77,29 @@ fn legacy_tauri_app_data_dir_for(identifier: &str) -> Option<PathBuf> {
|
||||
}
|
||||
}
|
||||
let home = std::env::var("HOME").ok().filter(|s| !s.is_empty())?;
|
||||
return Some(
|
||||
Some(
|
||||
PathBuf::from(home)
|
||||
.join(".local")
|
||||
.join("share")
|
||||
.join(identifier),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let home = std::env::var("HOME").ok().filter(|s| !s.is_empty())?;
|
||||
return Some(
|
||||
Some(
|
||||
PathBuf::from(home)
|
||||
.join("Library")
|
||||
.join("Application Support")
|
||||
.join(identifier),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let appdata = std::env::var("APPDATA").ok().filter(|s| !s.is_empty())?;
|
||||
return Some(PathBuf::from(appdata).join(identifier));
|
||||
Some(PathBuf::from(appdata).join(identifier))
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
|
||||
@@ -123,10 +121,7 @@ fn legacy_tauri_app_data_dir_for(identifier: &str) -> Option<PathBuf> {
|
||||
/// `paths.rs` migration already covers the user's transcripts and
|
||||
/// models, so even a total-failure here only loses webview-keyed state
|
||||
/// (preferences, session storage, plugin geometry).
|
||||
pub fn migrate_tauri_app_data_dir_with_paths(
|
||||
old: &Path,
|
||||
new: &Path,
|
||||
) -> AppDataMigrationStatus {
|
||||
pub fn migrate_tauri_app_data_dir_with_paths(old: &Path, new: &Path) -> AppDataMigrationStatus {
|
||||
let old_exists = old.exists();
|
||||
let new_exists = new.exists();
|
||||
|
||||
@@ -265,7 +260,10 @@ mod tests {
|
||||
assert!(leveldb.exists());
|
||||
|
||||
// Staging directory is cleaned up.
|
||||
assert!(!tmp.path().join("consulting.corbel.lumotia.migrating").exists());
|
||||
assert!(!tmp
|
||||
.path()
|
||||
.join("consulting.corbel.lumotia.migrating")
|
||||
.exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -329,6 +327,9 @@ mod tests {
|
||||
AppDataMigrationStatus::BothExistLegacyPreserved { .. }
|
||||
));
|
||||
|
||||
assert_eq!(fs::read(new.join("file.txt")).unwrap(), b"v2-edited-by-user");
|
||||
assert_eq!(
|
||||
fs::read(new.join("file.txt")).unwrap(),
|
||||
b"v2-edited-by-user"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,11 +56,7 @@ fn init_tracing_creates_log_file() {
|
||||
let entries: Vec<_> = fs::read_dir(&logs_dir)
|
||||
.expect("read tempdir")
|
||||
.filter_map(Result::ok)
|
||||
.filter(|e| {
|
||||
e.file_name()
|
||||
.to_string_lossy()
|
||||
.starts_with("lumotia")
|
||||
})
|
||||
.filter(|e| e.file_name().to_string_lossy().starts_with("lumotia"))
|
||||
.collect();
|
||||
|
||||
assert!(
|
||||
|
||||
Reference in New Issue
Block a user