-
Notifications
You must be signed in to change notification settings - Fork 0
[01/09] config: centralize Settings + path-aware load #123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting
crates/app/src/main.rs
Outdated
| let mut opts = AppRuntimeOptions { | ||
| device, | ||
| resampler_quality: match resampler_quality.to_lowercase().as_str() { | ||
| "fast" => ResamplerQuality::Fast, | ||
| "quality" => ResamplerQuality::Quality, | ||
| _ => ResamplerQuality::Balanced, | ||
| }, | ||
| activation_mode: match cli.activation_mode { | ||
| ActivationMode::Vad => RuntimeMode::Vad, | ||
| ActivationMode::Hotkey => RuntimeMode::Hotkey, | ||
| }, | ||
| resampler_quality, | ||
| activation_mode, | ||
| stt_selection, | ||
| #[cfg(feature = "text-injection")] | ||
| injection: if cfg!(feature = "text-injection") { | ||
| enable_device_monitor: settings.enable_device_monitor, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AppRuntimeOptions constructed with nonexistent field
The new settings integration tries to set enable_device_monitor when building AppRuntimeOptions, but that struct (see crates/app/src/runtime.rs) only contains device, resampler_quality, activation_mode, and stt_selection. The additional field does not exist, so the project will not compile. Either add the field to AppRuntimeOptions or remove the assignment.
Useful? React with 👍 / 👎.
| opts.injection = if cfg!(feature = "text-injection") { | ||
| Some(coldvox_app::runtime::InjectionOptions { | ||
| enable: cli.injection.enable, | ||
| allow_ydotool: cli.injection.allow_ydotool, | ||
| allow_kdotool: cli.injection.allow_kdotool, | ||
| allow_enigo: cli.injection.allow_enigo, | ||
| inject_on_unknown_focus: cli.injection.inject_on_unknown_focus, | ||
| restore_clipboard: cli.injection.restore_clipboard, | ||
| max_total_latency_ms: cli.injection.max_total_latency_ms, | ||
| per_method_timeout_ms: cli.injection.per_method_timeout_ms, | ||
| cooldown_initial_ms: cli.injection.cooldown_initial_ms, | ||
| enable: true, // Assuming text injection is enabled if the feature is on | ||
| allow_kdotool: settings.injection.allow_kdotool, | ||
| allow_enigo: settings.injection.allow_enigo, | ||
| inject_on_unknown_focus: settings.injection.inject_on_unknown_focus, | ||
| max_total_latency_ms: Some(settings.injection.max_total_latency_ms), | ||
| per_method_timeout_ms: Some(settings.injection.per_method_timeout_ms), | ||
| cooldown_initial_ms: Some(settings.injection.cooldown_initial_ms), | ||
| fail_fast: settings.injection.fail_fast, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InjectionOptions literal omits required fields and references unknown one
When text‑injection is enabled the struct literal for InjectionOptions does not provide values for mandatory fields (allow_ydotool, restore_clipboard) and also tries to set fail_fast, which is not part of InjectionOptions (see crates/app/src/runtime.rs lines 35‑48). This mismatched construction prevents the code from compiling. Either extend InjectionOptions to include these fields or adjust the literal to match the struct definition (possibly using ..Default::default() for unchanged fields).
Useful? React with 👍 / 👎.
Archive complete execution artifacts from 2025-10-08 refactor split: - split-validation.log: Complete Phase 1-3 execution log - pr-stack-summary.md: Executive summary and quick reference - pr-stack-tracker.md: Live progress tracker for Phases 4-6 - merge-stack.sh: Automated merge orchestration script - README.md: Directory overview and documentation Related PRs: #123-#131 Execution: 9 domain-based PRs from anchor/oct-06-2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Centralizes application configuration into a unified Settings loader with path-aware discovery and environment overrides, and updates the app to consume it. Also introduces default/override config files and prunes legacy CLI flags in favor of config-driven behavior.
- Introduces Settings with config crate integration (TOML + env mapping) and XDG-aware path discovery
- Refactors main to consume Settings, adds log pruning, and adjusts log levels
- Adds tests for Settings; updates Cargo to expose a lib crate and pulls in config dependency
Reviewed Changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/coldvox-foundation/src/state.rs | Lowers state transition log level from info to debug |
| crates/coldvox-foundation/src/shutdown.rs | Lowers shutdown log level from info to debug |
| crates/app/src/lib.rs | New Settings model, builder with defaults, env overrides, XDG discovery, and validation |
| crates/app/src/main.rs | Consumes Settings, adds log pruning, removes many CLI flags, wires injection/STT from settings |
| crates/app/tests/settings_test.rs | New integration tests for Settings (some currently ignored) |
| crates/app/Cargo.toml | Adds [lib] target and config dependency |
| config/default.toml | New default configuration |
| config/overrides.toml | Example/local overrides template |
| config/README.md | Configuration docs and deployment guidance |
| config/plugins.json | Example STT plugins configuration payload |
| activation_mode = "hotkey" # Maps to COLDVOX_ACTIVATION_MODE=hotkey | ||
|
|
||
| # Example: Override injection settings | ||
| [Injection] |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The table name should be lowercase to match the Settings field name and TOML case sensitivity. Change [Injection] to [injection] so values deserialize into Settings::injection.
| [Injection] | |
| [injection] |
| - **Overrides via Environment Variables**: Preferred for secrets and dynamic settings. Use `COLDVOX__` prefix: | ||
| - Example for production: `export COLDVOX_STT__PREFERRED=cloud_whisper; export COLDVOX_INJECTION__FAIL_FAST=true`. | ||
| - Nested: `COLDVOX_VAD__SENSITIVITY=0.8` overrides `[vad].sensitivity`. | ||
| - Set in deployment tools: Systemd (`Environment=`), Docker (`-e`), Kubernetes (Secrets/ConfigMaps). | ||
| - **Separate TOML Files for Non-Secrets**: Use `overrides.toml` (or env-specific like `staging.toml`) for bulk overrides. Extend the loader in `crates/app/src/main.rs` to support `COLDVOX_CONFIG_OVERRIDE_PATH=/path/to/staging.toml`. |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documented prefix is incorrect. The actual prefix is COLDVOX (single underscore after the prefix, double underscore for nesting), e.g., COLDVOX_STT__PREFERRED and COLDVOX_INJECTION__FAIL_FAST.
| # This file is not loaded by default; extend Settings::new() if needed. | ||
|
|
||
| # Example: Override injection settings | ||
| [Injection] |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a lowercase section header to match the Settings schema and TOML case sensitivity. Change [Injection] to [injection] in the example.
| [Injection] | |
| [injection] |
| CMD ["./coldvox-app"] | ||
| ``` | ||
| - For binary distributions: Include in a `config/` subdirectory next to the executable. | ||
| - **Runtime Loading**: The app loads `config/default.toml` relative to the working directory. XDG support not implemented; to add it, extend `Settings::new()` with XDG path lookup (see deployment docs for details). |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is outdated. Settings::discover_config_path already resolves XDG_CONFIG_HOME and ~/.config/coldvox/default.toml; update the docs to reflect that XDG paths are supported.
| - **Runtime Loading**: The app loads `config/default.toml` relative to the working directory. XDG support not implemented; to add it, extend `Settings::new()` with XDG path lookup (see deployment docs for details). | |
| - **Runtime Loading**: The app automatically searches for `default.toml` in XDG-compliant locations (e.g., `$XDG_CONFIG_HOME/coldvox/default.toml`), `~/.config/coldvox/default.toml`, and `config/default.toml` relative to the working directory. No manual extension is needed—XDG paths are supported by default (see deployment docs for details). |
| ## Deployment Considerations | ||
|
|
||
| When deploying ColdVox, handle configurations carefully to ensure security, flexibility, and reliability across environments. | ||
|
|
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The binary name is coldvox (per [[bin]] name), not coldvox-app. Update the Dockerfile example to COPY and run ./coldvox.
| #[derive(Parser, Debug)] | ||
| #[command(name = "coldvox", author, version, about = "ColdVox voice pipeline")] | ||
| struct Cli { | ||
| /// Preferred input device name (exact or substring) | ||
| #[arg(short = 'D', long = "device")] | ||
| device: Option<String>, | ||
|
|
||
| /// List available input devices and exit | ||
| #[arg(long = "list-devices")] | ||
| list_devices: bool, | ||
|
|
||
| /// Resampler quality: fast, balanced, quality | ||
| #[arg(long = "resampler-quality", default_value = "balanced")] | ||
| resampler_quality: String, | ||
|
|
||
| #[cfg(feature = "vosk")] | ||
| /// Enable transcription persistence to disk | ||
| #[arg(long = "save-transcriptions")] | ||
| save_transcriptions: bool, | ||
|
|
||
| #[cfg(feature = "vosk")] | ||
| /// Save audio alongside transcriptions | ||
| #[arg(long = "save-audio", requires = "save_transcriptions")] | ||
| save_audio: bool, | ||
|
|
||
| #[cfg(feature = "vosk")] | ||
| /// Output directory for transcriptions | ||
| #[arg(long = "output-dir", default_value = "transcriptions")] | ||
| output_dir: String, | ||
|
|
||
| #[cfg(feature = "vosk")] | ||
| /// Transcription format: json, csv, text | ||
| #[arg(long = "transcript-format", default_value = "json")] | ||
| transcript_format: String, | ||
|
|
||
| #[cfg(feature = "vosk")] | ||
| /// Keep transcription files for N days (0 = forever) | ||
| #[arg(long = "retention-days", default_value = "30")] | ||
| retention_days: u32, | ||
|
|
||
| /// Enable TUI dashboard | ||
| #[arg(long = "tui")] | ||
| tui: bool, | ||
|
|
||
| /// Activation mode: "vad" or "hotkey" | ||
| #[arg(long = "activation-mode", default_value = "hotkey", value_enum)] | ||
| activation_mode: ActivationMode, | ||
|
|
||
| #[command(flatten)] | ||
| stt: SttArgs, | ||
|
|
||
| #[cfg(feature = "text-injection")] | ||
| #[command(flatten)] | ||
| injection: InjectionArgs, | ||
| } | ||
|
|
||
| #[derive(Debug, Clone, Copy, ValueEnum, PartialEq)] | ||
| enum ActivationMode { | ||
| Vad, | ||
| Hotkey, | ||
| } | ||
|
|
||
| #[derive(Args, Debug)] | ||
| #[command(next_help_heading = "Speech-to-Text")] | ||
| struct SttArgs { | ||
| /// Preferred STT plugin ID (e.g., "vosk", "whisper", "mock") | ||
| #[arg(long = "stt-preferred", env = "COLDVOX_STT_PREFERRED")] | ||
| preferred: Option<String>, | ||
|
|
||
| /// Comma-separated list of fallback plugin IDs | ||
| #[arg( | ||
| long = "stt-fallbacks", | ||
| env = "COLDVOX_STT_FALLBACKS", | ||
| value_delimiter = ',' | ||
| )] | ||
| fallbacks: Option<Vec<String>>, | ||
|
|
||
| /// Require local processing (no cloud STT services) | ||
| #[arg(long = "stt-require-local", env = "COLDVOX_STT_REQUIRE_LOCAL")] | ||
| require_local: bool, | ||
|
|
||
| /// Maximum memory usage in MB | ||
| #[arg(long = "stt-max-mem-mb", env = "COLDVOX_STT_MAX_MEM_MB")] | ||
| max_mem_mb: Option<u32>, | ||
|
|
||
| /// Required language (ISO 639-1 code, e.g., "en", "fr") | ||
| #[arg(long = "stt-language", env = "COLDVOX_STT_LANGUAGE")] | ||
| language: Option<String>, | ||
|
|
||
| /// Number of consecutive errors before switching to fallback plugin | ||
| #[arg( | ||
| long = "stt-failover-threshold", | ||
| env = "COLDVOX_STT_FAILOVER_THRESHOLD", | ||
| default_value = "3" | ||
| )] | ||
| failover_threshold: u32, | ||
|
|
||
| /// Cooldown period in seconds before retrying a failed plugin | ||
| #[arg( | ||
| long = "stt-failover-cooldown-secs", | ||
| env = "COLDVOX_STT_FAILOVER_COOLDOWN_SECS", | ||
| default_value = "30" | ||
| )] | ||
| failover_cooldown_secs: u32, | ||
|
|
||
| /// Time to live in seconds for inactive models (GC threshold) | ||
| #[arg( | ||
| long = "stt-model-ttl-secs", | ||
| env = "COLDVOX_STT_MODEL_TTL_SECS", | ||
| default_value = "300" | ||
| )] | ||
| model_ttl_secs: u32, | ||
|
|
||
| /// Disable garbage collection of inactive models | ||
| #[arg(long = "stt-disable-gc", env = "COLDVOX_STT_DISABLE_GC")] | ||
| disable_gc: bool, | ||
|
|
||
| /// Interval in seconds for periodic metrics logging (0 to disable) | ||
| #[arg( | ||
| long = "stt-metrics-log-interval-secs", | ||
| env = "COLDVOX_STT_METRICS_LOG_INTERVAL_SECS", | ||
| default_value = "60" | ||
| )] | ||
| metrics_log_interval_secs: u32, | ||
|
|
||
| /// Enable debug dumping of transcription events to logs | ||
| #[arg(long = "stt-debug-dump-events", env = "COLDVOX_STT_DEBUG_DUMP_EVENTS")] | ||
| debug_dump_events: bool, | ||
|
|
||
| /// Automatically extract model from a zip archive if not found | ||
| #[arg( | ||
| long = "stt-auto-extract", | ||
| env = "COLDVOX_STT_AUTO_EXTRACT", | ||
| default_value = "true" | ||
| )] | ||
| auto_extract: bool, | ||
| } | ||
|
|
||
| #[cfg(feature = "text-injection")] | ||
| #[derive(Args, Debug)] | ||
| #[command(next_help_heading = "Text Injection")] | ||
| struct InjectionArgs { | ||
| /// Enable text injection after transcription | ||
| #[arg(long = "enable-text-injection", env = "COLDVOX_ENABLE_TEXT_INJECTION")] | ||
| enable: bool, | ||
|
|
||
| /// Allow ydotool as an injection fallback | ||
| #[arg(long = "allow-ydotool", env = "COLDVOX_ALLOW_YDOTOOL")] | ||
| allow_ydotool: bool, | ||
|
|
||
| /// Allow kdotool as an injection fallback | ||
| #[arg(long = "allow-kdotool", env = "COLDVOX_ALLOW_KDOTOOL")] | ||
| allow_kdotool: bool, | ||
|
|
||
| /// Allow enigo as an injection fallback | ||
| #[arg(long = "allow-enigo", env = "COLDVOX_ALLOW_ENIGO")] | ||
| allow_enigo: bool, | ||
|
|
||
| /// Attempt injection even if the focused application is unknown | ||
| #[arg( | ||
| long = "inject-on-unknown-focus", | ||
| env = "COLDVOX_INJECT_ON_UNKNOWN_FOCUS" | ||
| )] | ||
| inject_on_unknown_focus: bool, | ||
|
|
||
| /// Restore clipboard contents after injection | ||
| #[arg(long = "restore-clipboard", env = "COLDVOX_RESTORE_CLIPBOARD")] | ||
| restore_clipboard: bool, | ||
|
|
||
| /// Max total latency for an injection call (ms) | ||
| #[arg(long, env = "COLDVOX_INJECTION_MAX_LATENCY_MS")] | ||
| max_total_latency_ms: Option<u64>, | ||
|
|
||
| /// Timeout for each injection method (ms) | ||
| #[arg(long, env = "COLDVOX_INJECTION_METHOD_TIMEOUT_MS")] | ||
| per_method_timeout_ms: Option<u64>, | ||
|
|
||
| /// Initial cooldown on failure (ms) | ||
| #[arg(long, env = "COLDVOX_INJECTION_COOLDOWN_MS")] | ||
| cooldown_initial_ms: Option<u64>, | ||
| /// Exit immediately if all injection methods fail | ||
| #[arg(long = "injection-fail-fast")] | ||
| injection_fail_fast: bool, | ||
| } |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This removes previously supported CLI flags (device selection, resampler quality, STT/injection tuning). If CLI compatibility is important, consider keeping deprecated aliases that map into Settings (hidden or marked deprecated in clap), or document the breaking change and provide migration notes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirm, I believe that the intent here is that going forward, these will just be configured by file, and there will be no or few CLI flags.
@claude
| enable: true, // Assuming text injection is enabled if the feature is on | ||
| allow_kdotool: settings.injection.allow_kdotool, | ||
| allow_enigo: settings.injection.allow_enigo, | ||
| inject_on_unknown_focus: settings.injection.inject_on_unknown_focus, | ||
| max_total_latency_ms: Some(settings.injection.max_total_latency_ms), | ||
| per_method_timeout_ms: Some(settings.injection.per_method_timeout_ms), | ||
| cooldown_initial_ms: Some(settings.injection.cooldown_initial_ms), | ||
| fail_fast: settings.injection.fail_fast, | ||
| }) |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Injection is unconditionally enabled when the feature is compiled, removing the ability to disable it at runtime. Consider adding an enable flag to Settings (e.g., injection.enable: bool) and wiring it here as enable: settings.injection.enable.
| } | ||
|
|
||
| if !errors.is_empty() { | ||
| let error_msg = format!("Critical config validation errors: {:?}", errors); |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatting the vector with {:?} produces a debug dump; join the messages for readability. For example: errors.join("; ") or format them on newlines.
| let error_msg = format!("Critical config validation errors: {:?}", errors); | |
| let error_msg = format!( | |
| "Critical config validation errors: {}", | |
| errors.join("; ") | |
| ); |
|
@qwencoder ● PR #123 Review Complete Summary Config/Settings foundation PR that centralizes configuration with path-aware loading. Well-structured but has CI failures and some design concerns. Strengths ✅
Issues Blocking:
Code Quality:
Missing:
Recommendation Request Changes - Fix CI failures and address ignored tests before merge. Other issues are non-blocking but should be tracked. |
- Fix cache path mismatch: script now checks alternate cache locations (/vosk-models vs /vosk) with fallback logic - Switch to large production model: vosk-model-en-us-0.22 (1.8GB) - Update model checksum to match current alphacephei.com version - Add libvosk fallback: checks cache, alternate cache, and system paths - Make GITHUB_OUTPUT optional for local testing - Add comprehensive test suite: test_vosk_setup.sh mimics CI workflow - Add detailed verification report: VOSK_SETUP_VERIFICATION.md Resolves model download and linking failures in CI workflows. All verification tests pass locally on self-hosted runner. Tested: - Setup script execution (symlinks created correctly) - Build: cargo build -p coldvox-stt-vosk --features vosk ✅ - Unit tests: 3/3 passed ✅ - Model structure validation ✅
PR #123 Review - Compilation StatusCurrent StateThis branch does not compile standalone due to struct field mismatches in
This is expected - PR #123 introduces the Settings infrastructure, but Ignored Tests AnalysisThe 3 ignored tests for env var overrides (
RecommendationsOption A: Merge stack first, then test
Option B: Fix on this branch
Option C: Remove ignored tests for now
VerdictRecommend Option A - The CI failure (Vosk) is already fixed in commit Analysis via Claude Code - stacked PR review |
- Phase 0: Safety backups with UTC timestamps and atomic pushing - Phase 1: Fix 5 blocking issues (including PR #123 env var tests) - Phase 2: Sequential merge strategy - Phase 3: Validation and comparison with PR #134 - Phase 4: Decision matrix for choosing final approach - Incorporates expert feedback on git safety and atomic operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Fixes linker error 'unable to find library -lvosk' by: - Adding vendor/vosk/lib to rustc link search path - Setting rpath for runtime library discovery - Falling back to system paths (/usr/local/lib, /usr/lib64, /usr/lib) - Using cargo:rerun-if-changed for efficient rebuilds Addresses issue documented in docs/dev/THE_MISSING_LINK.md. Follows Rust best practices per Cargo book build script guidelines. Tested with: cargo check -p coldvox-stt-vosk --features vosk
- Remove non-existent 'enable_device_monitor' field from AppRuntimeOptions - Update InjectionOptions initialization to match actual struct fields - Add missing 'allow_ydotool' and 'restore_clipboard' fields This fixes compilation errors when building coldvox-app with vosk features.
Create complete runnerAgent documentation system for managing and optimizing the self-hosted GitHub Actions runner (laptop-extra). Structure: - README.md: Quick start guide with daily workflows and debugging commands - RunnerAgent.md: Complete architecture document with system design - IMPLEMENTATION.md: Usage patterns, integration guide, and next steps - prompts/: LLM assistant configurations for specialized tasks - debug_agent_prompt.md: CI failure diagnosis workflows - system_update_prompt.md: Dependency and toolchain maintenance - performance_monitor_prompt.md: Build/test optimization strategies Key features: - Executable commands for common operations (health checks, log analysis) - LLM-ready prompts for AI-assisted debugging with tools like gemini CLI - Local-first approach leveraging direct hardware access - Performance monitoring and optimization guidelines - Integration with existing CI workflows and scripts Benefits: - Self-service debugging without admin access - Faster iteration (test locally before pushing) - Performance visibility and tracking - Reproducible maintenance workflows Related: PR #123 (requires runner toolchain update to pass CI)
…ine/actions-runner/_work/ColdVox/ColdVox in key docs
* [08/09] logs: prune noisy hot paths; telemetry tweaks * fix: replace hardcoded device with env var and fallback chain - Use COLDVOX_TEST_DEVICE env var if set - Fall back to ctx.device from test context - Fall back to default device detection if neither specified - Improves portability across different hardware setups 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(logging): remove hardcoded device; add env/ctx fallback (#130) - Replace hardcoded "HyperX QuadCast" device in vad_mic.rs with flexible fallback: 1. Check COLDVOX_TEST_DEVICE env var first 2. Fall back to TestContext.device 3. Use None for default enumeration if neither specified - Add warning log when falling back to default enumeration - Add TODO(#130) comment for misnamed counter `requests_per_second` → `total_requests` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * [01/09] config: centralize Settings + path-aware load (#123) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * fix(ci): resolve Vosk setup issues for self-hosted runner - Fix cache path mismatch: script now checks alternate cache locations (/vosk-models vs /vosk) with fallback logic - Switch to large production model: vosk-model-en-us-0.22 (1.8GB) - Update model checksum to match current alphacephei.com version - Add libvosk fallback: checks cache, alternate cache, and system paths - Make GITHUB_OUTPUT optional for local testing - Add comprehensive test suite: test_vosk_setup.sh mimics CI workflow - Add detailed verification report: VOSK_SETUP_VERIFICATION.md Resolves model download and linking failures in CI workflows. All verification tests pass locally on self-hosted runner. Tested: - Setup script execution (symlinks created correctly) - Build: cargo build -p coldvox-stt-vosk --features vosk ✅ - Unit tests: 3/3 passed ✅ - Model structure validation ✅ * debugging * Add build.rs to link vendored libvosk at compile time Fixes linker error 'unable to find library -lvosk' by: - Adding vendor/vosk/lib to rustc link search path - Setting rpath for runtime library discovery - Falling back to system paths (/usr/local/lib, /usr/lib64, /usr/lib) - Using cargo:rerun-if-changed for efficient rebuilds Addresses issue documented in docs/dev/THE_MISSING_LINK.md. Follows Rust best practices per Cargo book build script guidelines. Tested with: cargo check -p coldvox-stt-vosk --features vosk * fix: Update main.rs to match runtime struct definitions - Remove non-existent 'enable_device_monitor' field from AppRuntimeOptions - Update InjectionOptions initialization to match actual struct fields - Add missing 'allow_ydotool' and 'restore_clipboard' fields This fixes compilation errors when building coldvox-app with vosk features. * chore: retrigger CI after runner restart * test: trigger CI after fixing Rust version * docs: Add comprehensive self-hosted runner management architecture Create complete runnerAgent documentation system for managing and optimizing the self-hosted GitHub Actions runner (laptop-extra). Structure: - README.md: Quick start guide with daily workflows and debugging commands - RunnerAgent.md: Complete architecture document with system design - IMPLEMENTATION.md: Usage patterns, integration guide, and next steps - prompts/: LLM assistant configurations for specialized tasks - debug_agent_prompt.md: CI failure diagnosis workflows - system_update_prompt.md: Dependency and toolchain maintenance - performance_monitor_prompt.md: Build/test optimization strategies Key features: - Executable commands for common operations (health checks, log analysis) - LLM-ready prompts for AI-assisted debugging with tools like gemini CLI - Local-first approach leveraging direct hardware access - Performance monitoring and optimization guidelines - Integration with existing CI workflows and scripts Benefits: - Self-service debugging without admin access - Faster iteration (test locally before pushing) - Performance visibility and tracking - Reproducible maintenance workflows Related: PR #123 (requires runner toolchain update to pass CI) * docs(runnerAgent): include absolute runner workspace path /home/coldaine/actions-runner/_work/ColdVox/ColdVox in key docs * docs(runnerAgent): add gemini-based runner debugger script and README note --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Coldaine <[email protected]> * [02/09] audio: capture lifecycle fix + ALSA stderr suppression (#124) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * fix(audio): decouple wav_file_loader decl, cfg(unix) + safety notes (#124) - Remove wav_file_loader module declaration from app/audio/mod.rs (decouples #124 from #127 dependency) - Remove misplaced STT plugins.json from crates/coldvox-audio/ (STT config belongs in app-level or config/ directory, not audio crate) - Add #[cfg(unix)] guards to stderr_suppressor module and usage (Unix-specific file descriptor operations) - Add comprehensive SAFETY documentation to all unsafe blocks in stderr_suppressor.rs explaining FD ownership and dup2 atomicity Note: coldvox-audio compiles and tests pass. coldvox-app has pre-existing API signature mismatches (AudioCaptureThread::spawn) that need separate fix. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> * [03/09] vad: windowing/debounce consistency (#125) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * [03/09] vad: windowing/debounce consistency --------- Co-authored-by: ColdVox Dev <[email protected]> * [04/09] stt: finalize handling + helpers (#126) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * [03/09] vad: windowing/debounce consistency * [04/09] stt: finalize handling + helpers * fix: add constants module declaration to coldvox-stt - Declare pub mod constants in lib.rs - Note: helpers.rs not declared due to circular dependency with coldvox-telemetry - helpers.rs is currently unused and can be integrated when telemetry refactor resolves cycle 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(stt): add module decls, clean imports, constants (#126) - Add constants module declaration to lib.rs - Move SttMetrics from processor.rs to types.rs (breaks circular dependency) - Clean imports in helpers.rs (remove circular import, alphabetize) - Replace magic numbers in processor.rs with named constants: - 16000 -> SAMPLE_RATE_HZ - 10 -> DEFAULT_BUFFER_DURATION_SECONDS - 100 -> LOGGING_INTERVAL_FRAMES - 5 -> SEND_TIMEOUT_SECONDS - Comment out helpers module (requires coldvox_telemetry, should move to app crate) Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> Co-authored-by: Coldaine <[email protected]>
* [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * [03/09] vad: windowing/debounce consistency * [04/09] stt: finalize handling + helpers * [05/09] app: unify VAD↔STT runtime + real WAV loader * [06/09] injection: clipboard-preserve + Wayland-first strategy * [07/09] tests: deterministic E2E + integration suites * fix: convert clipboard injector test to tokio::test - Replace futures::executor::block_on with async/await - Use #[tokio::test] instead of #[test] for async test - Eliminates need for futures crate dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: resolve compilation failures from missing .await Add .await to async StrategyManager::new() calls in integration tests. StrategyManager::new() is an async function that returns a Future, which must be awaited. Fixed 3 occurrences in: - text_injection_integration_test.rs (lines 55, 90, 119) * [08/09] logs: prune noisy hot paths; telemetry tweaks (#130) * [08/09] logs: prune noisy hot paths; telemetry tweaks * fix: replace hardcoded device with env var and fallback chain - Use COLDVOX_TEST_DEVICE env var if set - Fall back to ctx.device from test context - Fall back to default device detection if neither specified - Improves portability across different hardware setups 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(logging): remove hardcoded device; add env/ctx fallback (#130) - Replace hardcoded "HyperX QuadCast" device in vad_mic.rs with flexible fallback: 1. Check COLDVOX_TEST_DEVICE env var first 2. Fall back to TestContext.device 3. Use None for default enumeration if neither specified - Add warning log when falling back to default enumeration - Add TODO(#130) comment for misnamed counter `requests_per_second` → `total_requests` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * [01/09] config: centralize Settings + path-aware load (#123) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * fix(ci): resolve Vosk setup issues for self-hosted runner - Fix cache path mismatch: script now checks alternate cache locations (/vosk-models vs /vosk) with fallback logic - Switch to large production model: vosk-model-en-us-0.22 (1.8GB) - Update model checksum to match current alphacephei.com version - Add libvosk fallback: checks cache, alternate cache, and system paths - Make GITHUB_OUTPUT optional for local testing - Add comprehensive test suite: test_vosk_setup.sh mimics CI workflow - Add detailed verification report: VOSK_SETUP_VERIFICATION.md Resolves model download and linking failures in CI workflows. All verification tests pass locally on self-hosted runner. Tested: - Setup script execution (symlinks created correctly) - Build: cargo build -p coldvox-stt-vosk --features vosk ✅ - Unit tests: 3/3 passed ✅ - Model structure validation ✅ * debugging * Add build.rs to link vendored libvosk at compile time Fixes linker error 'unable to find library -lvosk' by: - Adding vendor/vosk/lib to rustc link search path - Setting rpath for runtime library discovery - Falling back to system paths (/usr/local/lib, /usr/lib64, /usr/lib) - Using cargo:rerun-if-changed for efficient rebuilds Addresses issue documented in docs/dev/THE_MISSING_LINK.md. Follows Rust best practices per Cargo book build script guidelines. Tested with: cargo check -p coldvox-stt-vosk --features vosk * fix: Update main.rs to match runtime struct definitions - Remove non-existent 'enable_device_monitor' field from AppRuntimeOptions - Update InjectionOptions initialization to match actual struct fields - Add missing 'allow_ydotool' and 'restore_clipboard' fields This fixes compilation errors when building coldvox-app with vosk features. * chore: retrigger CI after runner restart * test: trigger CI after fixing Rust version * docs: Add comprehensive self-hosted runner management architecture Create complete runnerAgent documentation system for managing and optimizing the self-hosted GitHub Actions runner (laptop-extra). Structure: - README.md: Quick start guide with daily workflows and debugging commands - RunnerAgent.md: Complete architecture document with system design - IMPLEMENTATION.md: Usage patterns, integration guide, and next steps - prompts/: LLM assistant configurations for specialized tasks - debug_agent_prompt.md: CI failure diagnosis workflows - system_update_prompt.md: Dependency and toolchain maintenance - performance_monitor_prompt.md: Build/test optimization strategies Key features: - Executable commands for common operations (health checks, log analysis) - LLM-ready prompts for AI-assisted debugging with tools like gemini CLI - Local-first approach leveraging direct hardware access - Performance monitoring and optimization guidelines - Integration with existing CI workflows and scripts Benefits: - Self-service debugging without admin access - Faster iteration (test locally before pushing) - Performance visibility and tracking - Reproducible maintenance workflows Related: PR #123 (requires runner toolchain update to pass CI) * docs(runnerAgent): include absolute runner workspace path /home/coldaine/actions-runner/_work/ColdVox/ColdVox in key docs * docs(runnerAgent): add gemini-based runner debugger script and README note --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Coldaine <[email protected]> * [02/09] audio: capture lifecycle fix + ALSA stderr suppression (#124) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * fix(audio): decouple wav_file_loader decl, cfg(unix) + safety notes (#124) - Remove wav_file_loader module declaration from app/audio/mod.rs (decouples #124 from #127 dependency) - Remove misplaced STT plugins.json from crates/coldvox-audio/ (STT config belongs in app-level or config/ directory, not audio crate) - Add #[cfg(unix)] guards to stderr_suppressor module and usage (Unix-specific file descriptor operations) - Add comprehensive SAFETY documentation to all unsafe blocks in stderr_suppressor.rs explaining FD ownership and dup2 atomicity Note: coldvox-audio compiles and tests pass. coldvox-app has pre-existing API signature mismatches (AudioCaptureThread::spawn) that need separate fix. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> * [03/09] vad: windowing/debounce consistency (#125) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * [03/09] vad: windowing/debounce consistency --------- Co-authored-by: ColdVox Dev <[email protected]> * [04/09] stt: finalize handling + helpers (#126) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * [03/09] vad: windowing/debounce consistency * [04/09] stt: finalize handling + helpers * fix: add constants module declaration to coldvox-stt - Declare pub mod constants in lib.rs - Note: helpers.rs not declared due to circular dependency with coldvox-telemetry - helpers.rs is currently unused and can be integrated when telemetry refactor resolves cycle 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(stt): add module decls, clean imports, constants (#126) - Add constants module declaration to lib.rs - Move SttMetrics from processor.rs to types.rs (breaks circular dependency) - Clean imports in helpers.rs (remove circular import, alphabetize) - Replace magic numbers in processor.rs with named constants: - 16000 -> SAMPLE_RATE_HZ - 10 -> DEFAULT_BUFFER_DURATION_SECONDS - 100 -> LOGGING_INTERVAL_FRAMES - 5 -> SEND_TIMEOUT_SECONDS - Comment out helpers module (requires coldvox_telemetry, should move to app crate) Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> Co-authored-by: Coldaine <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> Co-authored-by: Coldaine <[email protected]>
* [08/09] logs: prune noisy hot paths; telemetry tweaks * fix: replace hardcoded device with env var and fallback chain - Use COLDVOX_TEST_DEVICE env var if set - Fall back to ctx.device from test context - Fall back to default device detection if neither specified - Improves portability across different hardware setups 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(logging): remove hardcoded device; add env/ctx fallback (#130) - Replace hardcoded "HyperX QuadCast" device in vad_mic.rs with flexible fallback: 1. Check COLDVOX_TEST_DEVICE env var first 2. Fall back to TestContext.device 3. Use None for default enumeration if neither specified - Add warning log when falling back to default enumeration - Add TODO(#130) comment for misnamed counter `requests_per_second` → `total_requests` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * [01/09] config: centralize Settings + path-aware load (#123) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * fix(ci): resolve Vosk setup issues for self-hosted runner - Fix cache path mismatch: script now checks alternate cache locations (/vosk-models vs /vosk) with fallback logic - Switch to large production model: vosk-model-en-us-0.22 (1.8GB) - Update model checksum to match current alphacephei.com version - Add libvosk fallback: checks cache, alternate cache, and system paths - Make GITHUB_OUTPUT optional for local testing - Add comprehensive test suite: test_vosk_setup.sh mimics CI workflow - Add detailed verification report: VOSK_SETUP_VERIFICATION.md Resolves model download and linking failures in CI workflows. All verification tests pass locally on self-hosted runner. Tested: - Setup script execution (symlinks created correctly) - Build: cargo build -p coldvox-stt-vosk --features vosk ✅ - Unit tests: 3/3 passed ✅ - Model structure validation ✅ * debugging * Add build.rs to link vendored libvosk at compile time Fixes linker error 'unable to find library -lvosk' by: - Adding vendor/vosk/lib to rustc link search path - Setting rpath for runtime library discovery - Falling back to system paths (/usr/local/lib, /usr/lib64, /usr/lib) - Using cargo:rerun-if-changed for efficient rebuilds Addresses issue documented in docs/dev/THE_MISSING_LINK.md. Follows Rust best practices per Cargo book build script guidelines. Tested with: cargo check -p coldvox-stt-vosk --features vosk * fix: Update main.rs to match runtime struct definitions - Remove non-existent 'enable_device_monitor' field from AppRuntimeOptions - Update InjectionOptions initialization to match actual struct fields - Add missing 'allow_ydotool' and 'restore_clipboard' fields This fixes compilation errors when building coldvox-app with vosk features. * chore: retrigger CI after runner restart * test: trigger CI after fixing Rust version * docs: Add comprehensive self-hosted runner management architecture Create complete runnerAgent documentation system for managing and optimizing the self-hosted GitHub Actions runner (laptop-extra). Structure: - README.md: Quick start guide with daily workflows and debugging commands - RunnerAgent.md: Complete architecture document with system design - IMPLEMENTATION.md: Usage patterns, integration guide, and next steps - prompts/: LLM assistant configurations for specialized tasks - debug_agent_prompt.md: CI failure diagnosis workflows - system_update_prompt.md: Dependency and toolchain maintenance - performance_monitor_prompt.md: Build/test optimization strategies Key features: - Executable commands for common operations (health checks, log analysis) - LLM-ready prompts for AI-assisted debugging with tools like gemini CLI - Local-first approach leveraging direct hardware access - Performance monitoring and optimization guidelines - Integration with existing CI workflows and scripts Benefits: - Self-service debugging without admin access - Faster iteration (test locally before pushing) - Performance visibility and tracking - Reproducible maintenance workflows Related: PR #123 (requires runner toolchain update to pass CI) * docs(runnerAgent): include absolute runner workspace path /home/coldaine/actions-runner/_work/ColdVox/ColdVox in key docs * docs(runnerAgent): add gemini-based runner debugger script and README note --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Coldaine <[email protected]> * [02/09] audio: capture lifecycle fix + ALSA stderr suppression (#124) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * fix(audio): decouple wav_file_loader decl, cfg(unix) + safety notes (#124) - Remove wav_file_loader module declaration from app/audio/mod.rs (decouples #124 from #127 dependency) - Remove misplaced STT plugins.json from crates/coldvox-audio/ (STT config belongs in app-level or config/ directory, not audio crate) - Add #[cfg(unix)] guards to stderr_suppressor module and usage (Unix-specific file descriptor operations) - Add comprehensive SAFETY documentation to all unsafe blocks in stderr_suppressor.rs explaining FD ownership and dup2 atomicity Note: coldvox-audio compiles and tests pass. coldvox-app has pre-existing API signature mismatches (AudioCaptureThread::spawn) that need separate fix. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> * [03/09] vad: windowing/debounce consistency (#125) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * [03/09] vad: windowing/debounce consistency --------- Co-authored-by: ColdVox Dev <[email protected]> * [04/09] stt: finalize handling + helpers (#126) * [01/09] config: centralize Settings + path-aware load * Add config dependency and lib section to Cargo.toml * Update Cargo.lock for config dependency * [02/09] audio: capture lifecycle fix + ALSA stderr suppression * [03/09] vad: windowing/debounce consistency * [04/09] stt: finalize handling + helpers * fix: add constants module declaration to coldvox-stt - Declare pub mod constants in lib.rs - Note: helpers.rs not declared due to circular dependency with coldvox-telemetry - helpers.rs is currently unused and can be integrated when telemetry refactor resolves cycle 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(stt): add module decls, clean imports, constants (#126) - Add constants module declaration to lib.rs - Move SttMetrics from processor.rs to types.rs (breaks circular dependency) - Clean imports in helpers.rs (remove circular import, alphabetize) - Replace magic numbers in processor.rs with named constants: - 16000 -> SAMPLE_RATE_HZ - 10 -> DEFAULT_BUFFER_DURATION_SECONDS - 100 -> LOGGING_INTERVAL_FRAMES - 5 -> SEND_TIMEOUT_SECONDS - Comment out helpers module (requires coldvox_telemetry, should move to app crate) Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> --------- Co-authored-by: ColdVox Dev <[email protected]> Co-authored-by: Claude <[email protected]> Co-authored-by: Coldaine <[email protected]>
Summary
Part 1 of 9 in the domain-based refactor split (see execution plan).
Centralizes configuration management with path-aware loading for Settings and adds the config crate dependency.
Changes
Config Infrastructure
config/default.tomlandconfig/overrides.tomlfor declarative configurationconfigcrate dependency (v0.14) with TOML support[lib]section incrates/app/Cargo.tomlfor library crateFoundation Layer
crates/coldvox-foundation/**: Core app scaffolding and foundation typesCOLDVOX_*prefix)Integration
crates/app/src/lib.rs: Settings struct and config loadingcrates/app/src/main.rs: Config integration into main binarycrates/app/tests/settings_test.rs: Test harness for SettingsDependencies
main)Validation
Metrics
Review Notes
Stack position: 1/9
Next PR: #2 (audio-capture)