Files
Jake 26c7307607
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
agent: lumotia-rebrand — docs, scripts, root config, residuals
Phase 9 of the rebrand cascade. Sweep covers everything the Phase 8
frontend pass deliberately skipped: docs/, root markdown, scripts,
Cargo.toml descriptions, code comments that survived earlier
word-boundary sed, plus a handful of identifiers caught on the final
verify pass.

transcription-app changes:
- README.md, HANDOVER.md, KNOWN-ISSUES.md, run.sh — magnotia/Magnotia
  -> lumotia/Lumotia.
- docs/ — sweep across all subdirs except docs/handovers/ (preserved
  as immutable audit trail). Includes architecture-map references
  to magnotia_core::*, magnotia_storage::*, etc. now pointing at
  lumotia_*; dev-setup.md tracing output examples (lumotia_startup
  target); brief/ + superpowers/ + issues/ + whisper-ecosystem/ +
  audit/.
- Cargo.toml descriptions on 9 crates (core, audio, cloud-providers,
  hotkey, llm, mcp, plus referenced others).
- crates/core/src/{error,hardware,recommendation,paths}.rs +
  crates/audio/src/wav.rs + crates/llm/src/model_manager.rs +
  crates/cloud-providers/src/keystore.rs + crates/mcp/src/lib.rs —
  doc comments and a model-manager user-agent string.
- Caught on final pass: BroadcastChannel("magnotia_task_sync") -> ...
  ("lumotia_task_sync"); magnotia_locale i18n localStorage key
  renamed + migration shim added; CSS keyframe names
  magnotiaPulse / magnotiaBar / magnotiaFade renamed in the design-
  system kit; magnotia_viewer_item / magnotia_viewer_mode handoff
  keys renamed in HistoryPage + viewer/+page.svelte; src/assets/
  wordmark.svg text.
- src-tauri/src/lib.rs comment cleanup ("magnotia era" was sed'd
  to "lumotia era" earlier — restored).

Preserved (intentional):
- crates/core/src/paths.rs — keeps "magnotia" / "Magnotia" / ".magnotia"
  legacy detection strings in legacy_and_target_paths() so the
  migration shim can still find user data from the magnotia era.
- src/lib/stores/{page,focusTimer}.svelte.ts + src/lib/i18n/index.ts
  — migration call sites reference the legacy magnotia keys
  deliberately.
- docs/handovers/ — historical audit trail.

cargo build --workspace passes. npm run check: 0 errors / 0 warnings
(3958 files). cargo test --workspace: 339 pass / 0 fail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:38:03 +01:00

4.7 KiB

name, type, slice, last_verified
name type slice last_verified
Core recommendation scoring architecture-map-page 05-core-storage-hotkey-build 2026/05/09

Core recommendation scoring

Where you are: Architecture mapCore, Storage, Hotkey, Build → Core recommendation scoring

Plain English summary. Given a SystemProfile (RAM, CPU, GPU, OS), score every model in the registry and rank them. The top entry is what Lumotia recommends. No boolean flags or scattered "is recommended" markers — position in the ranked list is the recommendation.

At a glance

  • File: crates/core/src/recommendation.rs (197 LOC, 113 of which are tests).
  • External deps: standard library only.
  • Public surface: ScoredModel, score_model, rank_recommendations.
  • Consumers: slice 2 model commands (frontend exposes the ranked list), the model picker UI (slice 1).

What's in here

ScoredModelcrates/core/src/recommendation.rs:7

pub struct ScoredModel {
    pub entry: &'static ModelEntry,
    pub score: f64,
    pub reason: String,
}

Borrows the registry entry by 'static reference (no allocation per call). reason is a user-facing explanatory string, prefilled with model.description if no override applied.

score_model(model, profile) -> Option<ScoredModel>crates/core/src/recommendation.rs:15

Pure function. Returns None when the model exceeds the system's RAM budget. Otherwise computes:

Component Score
SpeedTier::Instant +40
SpeedTier::Fast +30
SpeedTier::Moderate +20
SpeedTier::Slow +10
AccuracyTier::Excellent +30
AccuracyTier::Great +20
AccuracyTier::Good +10
GPU acceleration available for this model's engine +15
Headroom > 4 GB above model.ram_required +10

GPU acceleration matrix (recommendation.rs:36-49):

  • Whisper: any of metal, vulkan, cuda.
  • Parakeet / Moonshine: cuda or vulkan.

When GPU acceleration applies, reasons.push("GPU accelerated on your system"). Otherwise reason = model.description.to_string().

rank_recommendations(profile) -> Vec<ScoredModel>crates/core/src/recommendation.rs:71

Filters out registry entries that exceed RAM, scores the rest, sorts descending by score, returns the vector. partial_cmp falls through to Ordering::Equal if NaN appears (defensive; the scoring path can't produce NaN today).

Data flow / contract

  • Pure function over &SystemProfile and the &'static [ModelEntry] from the registry.
  • Order is fully determined by score, with ties broken by registry order (which is what sort_by preserves).
  • The "Parakeet first when fits" expectation is asserted by a test at recommendation.rs:184: any machine with enough RAM for Parakeet sees Parakeet at index 0.

Tests

6 tests in crates/core/src/recommendation.rs:85-197. Test fixtures profile_with_ram and profile_with_gpu build minimal SystemProfiles.

  • score_model_excludes_models_exceeding_available_ram — RAM budget guard.
  • score_model_includes_models_fitting_in_ram — happy path.
  • score_model_boosts_gpu_accelerated_models — GPU bonus is real.
  • rank_recommendations_places_highest_score_first — sort invariant.
  • rank_recommendations_returns_empty_for_very_low_ram — degenerate case.
  • parakeet_is_top_recommendation_when_hardware_supports_it — asserts the implicit policy that English-speaking users on capable hardware see Parakeet first because it beats Whisper on English at lower latency.

Watch-outs

  • No CPU-feature gate. A pre-AVX2 CPU does not down-rank Whisper or Parakeet entries. The runtime-capabilities banner (slice 2) handles that user-facing warning. Worth considering whether a hard down-rank ought to live here too.
  • Recommendation ignores download cost. A user on a slow connection still sees whisper-distil-large-v3 ranked first because it scores 30+30+10 = 70 against Parakeet's 40+20+10 = 70 (tie, registry order picks Parakeet). On a 4 GB-RAM machine, only whisper-base-en and whisper-tiny-en survive RAM filtering, so the ordering is well-behaved on low-end hardware.
  • GPU scoring keys off the Engine variant, not the model size. A 75 MB Whisper Tiny on a Vulkan GPU still gets the +15 bonus, which is technically correct (the inference does run on GPU) but is a marginal preference signal at that size.
  • reason is String, not a structured enum. UI that wants to badge the reason ("GPU accelerated", "Best for your RAM") needs to parse the string today. Worth pivoting to a discriminated union when more reasons land.

See also