Files
Lumotia/docs/architecture-map/README.md
jars a1f3f3f134 docs: architecture map (initial 5-slice generation, 105 pages)
Five-slice navigable map of the entire codebase under
docs/architecture-map/. Each slice is a self-contained
breadcrumbed sub-tree:

  01-frontend (16)              Svelte/SvelteKit UI
  02-tauri-runtime (26)         src-tauri commands + lifecycle
  03-audio-transcription (16)   audio + transcription crates
  04-llm-formatting-mcp (19)    llm, ai-formatting, mcp, cloud
  05-core-storage-hotkey-build  core, storage, hotkey, workspace,
                          (26) CI, dev glue

Plus master README.md and data-flow-end-to-end.md tracing
audio bytes from microphone to FTS5 search to MCP read.

Generated by 5 parallel subagents on 2026/05/09 against
HEAD 3c47000. Each page has YAML frontmatter, file:line code
refs, sibling cross-links, plain-English summaries.

Aggregated debt surfaced (full lists in master README):
RB-08 macOS power assertion, schema head drift v14 vs v15,
VAD blocked on ort version conflict, streaming primitives
not wired into live.rs, no prompt versioning, MCP has no
auth, cloud-providers in-memory keystore, SettingsPage
2 484 LOC, commands/live.rs 1 737 LOC, dual theme system,
brand rename to Lumenote pending across the codebase.

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

16 KiB

name, type, last_verified
name type last_verified
Magnotia architecture map architecture-map-root-index 2026/05/09

Magnotia architecture map

Where you are: Architecture map root. Reading order if this is your first time: read this page top to bottom, pick the slice that matches what you are trying to do, follow the breadcrumb trail.

What Magnotia is in 60 seconds

Magnotia is a local-first dictation desktop app. You press a hotkey, you speak, your speech becomes formatted text on disk and on the clipboard. Everything that touches your voice or your transcript runs on your own machine. Zero telemetry, zero analytics, no calls home unless you turn on auto-update.

It is a Tauri 2 app. The shell is Svelte 5. The brain is a Rust workspace of nine crates. Speech-to-text runs through Whisper (whisper-rs) by default with Parakeet (transcribe-rs ONNX) as an alternative. Optional cleanup runs through a local llama-cpp-2 LLM (Qwen3.5 / 3.6, four-tier model picker). Transcripts live in a SQLite database with a FTS5 full-text index. A standalone magnotia-mcp binary opens that database read-only and serves four tools over the Model Context Protocol so external agents can read your history without write access.

Targets: Linux (primary, Wayland-friendly), macOS, Windows. Android is on the roadmap (a few crate features carry android cfgs).

Brand rename in flight. Magnotia was approved as "Lumenote" on 2026/05/08. The codebase still says "magnotia" and "Magnotia" everywhere. The rename is a separate session.

The three layers

┌─────────────────────────────────────────────────────────────────────┐
│ Frontend  (slice 01)                                                │
│ Svelte 5 + SvelteKit. 4 windows, 7 pages, 25 components, 10 stores. │
│ ~17 200 LOC.                                                        │
├─────────────────────────────────────────────────────────────────────┤
│ Tauri runtime  (slice 02)                                           │
│ src-tauri/. 91 commands across 22 modules + 3 utility modules,      │
│ system tray, ACL capabilities, plugins, panic + log + CSP guards.   │
├─────────────────────────────────────────────────────────────────────┤
│ Rust workspace                                                      │
│ ┌────────────────────┬──────────────────────┬─────────────────────┐ │
│ │ Audio +            │ LLM + Formatting +   │ Core + Storage +    │ │
│ │ Transcription      │ MCP + Cloud          │ Hotkey + Build      │ │
│ │ (slice 03)         │ (slice 04)           │ (slice 05)          │ │
│ │ magnotia-audio     │ magnotia-llm         │ magnotia-core       │ │
│ │ magnotia-          │ magnotia-            │ magnotia-storage    │ │
│ │   transcription    │   ai-formatting      │ magnotia-hotkey     │ │
│ │                    │ magnotia-mcp         │ workspace + CI      │ │
│ │                    │ magnotia-            │                     │ │
│ │                    │   cloud-providers    │                     │ │
│ └────────────────────┴──────────────────────┴─────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

The frontend never touches the filesystem, the audio device, the models, or the LLM directly. Everything that crosses the WebView boundary uses invoke() (calling a Rust command) or Tauri events (one direction or the other). The Rust workspace is the brain. The Tauri layer is the integration surface.

Slices

# Slice Owns Files
01 Frontend Svelte UI, routes, pages, components, stores, i18n, design system, the WebView side of the bridge 16
02 Tauri runtime App lifecycle, 91 commands, system tray, ACL, plugins, configs, build.rs 26
03 Audio + Transcription Microphone capture, resampling, VAD, file decode, Whisper + Parakeet engines, streaming primitives, model manager 16
04 LLM + Formatting + MCP Llama-cpp engine, four LLM surfaces (cleanup, decompose, extract tasks, content tags), formatting pipeline, MCP server, cloud-provider stubs 19
05 Core + Storage + Hotkey + Build Shared types, hardware probe, power, thread tuning, model registry, SQLite + FTS5 + 15 migrations, evdev hotkey listener, workspace, CI 26

103 markdown pages in total under this directory.

Data flow

For an end-to-end trace of a single recording session from microphone to FTS5 search to MCP read, see data-flow-end-to-end.md.

"I want to find X"

If you want to ... Start here
Understand the dictation UI 01-frontend/pages/dictation.md
Add a new Tauri command 02-tauri-runtime/app-lifecycle.md and the relevant module under 02-tauri-runtime/commands/
Touch microphone capture or device handling 03-audio-transcription/audio-capture-pipeline.md
Change resampler or VAD behaviour 03-audio-transcription/audio-resampling.md and audio-vad.md
Wire a new Whisper or Parakeet model 03-audio-transcription/transcription-model-manager.md and 05-core-storage-hotkey-build/core-model-registry.md
Edit a system prompt or GBNF grammar 04-llm-formatting-mcp/llm-prompts-and-grammars.md
Tune the formatting pipeline (filler, British English, anti-hallucination) 04-llm-formatting-mcp/formatting-pipeline.md
Expose a new MCP tool 04-llm-formatting-mcp/mcp-server.md and mcp-tools.md
Add a database column or migration 05-core-storage-hotkey-build/storage-schema-and-migrations.md
Search transcripts (FTS5) 05-core-storage-hotkey-build/storage-fts5-search.md
Change hotkey behaviour on Linux 05-core-storage-hotkey-build/hotkey-linux-evdev.md
Tune inference threads / power / GPU offload 05-core-storage-hotkey-build/core-tuning.md and core-power.md
Adjust CI gates or release artefacts 05-core-storage-hotkey-build/ci-pipeline.md
Touch ACL / capabilities 02-tauri-runtime/capabilities-and-acl.md
Trace what every invoke() call does 01-frontend/frontend-tauri-bridge.md → match command name to file under 02-tauri-runtime/commands/
Understand model recommendation logic 05-core-storage-hotkey-build/core-recommendation.md

Cross-cutting concerns and known debt (aggregated 2026/05/09)

Open items surfaced by the slice maps. Each slice's README has its own debt section with the full detail.

Release blockers (gating v0.1)

  • RB-08 macOS power assertion (MAJOR, open). PowerAssertion::begin is a non-functional stub awaiting an objc2 rewrite plus runtime verification on Apple Silicon. Source: 02-tauri-runtime/commands/power-and-security.md. Ref HANDOVER.md.
  • PowerAssertion is a no-op on Linux and Windows too (separate from RB-08). Doc comments promise logind inhibitors and SetThreadExecutionState; neither implemented. Long Linux dictation can be idled by the compositor.

Brand rename pending

  • The codebase still says "magnotia" and "Magnotia" everywhere. Strings include "magnotia live dictation session", magnotia_preferences settings key, magnotia_settings localStorage key, prefixed events (magnotia:hotkey-pressed, magnotia:llm-download-progress, magnotia:open-wind-down, magnotia:preferences-changed), the bundle identifier uk.co.corbel.magnotia, every crate name (magnotia-core, magnotia-audio, etc), the magnotia-mcp binary, the brand asset folders. A rebrand sweep is a single dedicated session.

Bridge surface drift

  • Slice 02 registers 91 Tauri commands. Slice 01 invokes 60. The 31 unaccounted commands are likely registered for tests, internal lifecycle, or removed callers. Worth an audit pass.
  • Backend events emitted but not listened to (apparent). runtime-warning, transcription-result, native-pcm, magnotia:hotkey-released. Some may be deprecated, some may be observed only in specific routes. Verify before any cleanup.

Schema drift vs HANDOVER

  • HANDOVER.md (2026/04/25) quotes schema head v14. Disk head is v15 (idx_transcripts_profile_created). HANDOVER needs a refresh or a session-end note.

Audio pipeline gaps

  • VAD is a stub in magnotia-audio because both candidate Silero crates pin ort 2.0.0-rc.10 while transcribe-rs (Parakeet) needs 2.0.0-rc.12. Live capture leans on the energy-based RmsVadChunker in magnotia-transcription as a working fallback. Two VADs in two crates with no shared code or thresholds.
  • Streaming primitives (RmsVadChunker, LocalAgreement, trim_buffer_to_commit_point) are unit-tested but not yet wired into src-tauri/src/commands/live.rs. Comments in streaming/mod.rs, buffer_trim.rs, commit_policy.rs flag the integration as a follow-up.

LLM and formatting

  • No prompt versioning. No PROMPT_VERSION constant. Cached cleanup output will silently drift across prompt revisions.
  • Trivial-true GPU cross-check (commit 052265b). gpu_offloaded derived from use_gpu && gpu_layers >= n_layer is provably true today because gpu_layers = u32::MAX whenever use_gpu is set. Real residency observability needs llama.cpp log parsing.
  • MAX_CONTEXT_TOKENS is a process-wide cap of 8192 regardless of model tier. The 27B tier has a much larger native context that is never advertised.
  • MAGNOTIA_LLM_TEST_MODEL env-var gate is the only thing keeping the LLM smoke tests honest. Worth documenting in a contributor note.
  • British English regex misses -ing forms of -ize verbs (e.g. organizing slips through unconverted).
  • Multi-token phrase repetition not detected by the anti-hallucination filter. Five repetitions of "thank you" does not trigger.

MCP and security

  • MCP has no auth. Stdio is the trust boundary. Any future HTTP / SSE transport needs an auth layer before it ships.
  • magnotia-cloud-providers is empty scaffolding. In-memory keystore only. API keys vanish on restart. Documented TODO for keyring migration.

Frontend debt

  • SettingsPage.svelte is 2 484 LOC and Phase 9c handover already deferred the seven-group restructure plus search box.
  • Dual theme system. settings.theme ("Light" / "Dark" / "System") and preferences.theme ("light" / "dark" / "system") coexist with a migration $effect running every cycle.
  • @ts-nocheck on six files including +layout.svelte and four pages.
  • Triple transcript font-size knobs are in tension and likely drifted.
  • i18n is a stub. Each locale carries 19 lines.
  • Two font directories (src/fonts/ and static/fonts/) ship the same five woff2 files.
  • Default SvelteKit demo assets (static/svelte.svg, tauri.svg, vite.svg) likely unused.
  • Dead profiles route. Rewritten to settings at +page.svelte:13.

Tauri runtime debt

  • commands::live is 1 737 LOC in one file. Splitting per concern (runtime, speech gate, dedup, chunker, progressive WAV) is overdue.
  • build.rs link arg --allow-multiple-definition masks a real ggml duplication issue between whisper-rs-sys and llama-cpp-sys-2. Documented as INTERIM.
  • Updater stubs ship disabled. install_update returns "Updates are disabled until release signing is configured." Matching tauri.conf.json plugins.updater block is absent.
  • Production crash dumps lack stack traces because RUST_BACKTRACE is not set in the packaged binary and the panic hook does not capture a backtrace.
  • commands::tasks::decompose_and_store and extract_tasks_from_transcript_cmd lack PowerAssertion::begin despite running multi-second LLM inference. commands::llm::cleanup_transcript_text_cmd has it; tasks should too.
  • commands::transcribe_pcm does not call ensure_model_loaded unlike its file sibling. Asymmetry could panic if invoked before a load step.
  • tauri-plugin-cloud-providers crate is depended-on in Cargo.toml but no command file imports it. Reserved for future upload flow.
  • parallel_mode_available hard-wired to false in commands/models.rs:509. Phase A.4 marker for unblocking.

Build / CI / dev glue

  • run.sh hard-codes LIBCLANG_PATH=/usr/lib64/llvm21/lib64. Fedora 41 default. Breaks on Debian / Ubuntu / macOS without override.
  • src-tauri/.cargo/config.toml hard-codes LIBCLANG_PATH = "C:\\Program Files\\LLVM\\bin" for Windows.
  • No code signing. Apple and Windows signing env blocks are commented out. First-run users hit Gatekeeper / SmartScreen.
  • tauri-action@v0 is unpinned. Floats. Pin before v0.1.
  • pcm-processor.js hard-codes 16000 and 8000 which must move in lock-step with magnotia_core::constants::{WHISPER_SAMPLE_RATE, MIN_CHUNK_SAMPLES}.
  • uuid Cargo feature is v4 despite the storage Cargo.toml comment claiming "v7 random". Cosmetic but worth cleaning up.
  • GPU probe is a stub. magnotia_core::hardware::probe_gpu() returns None; no NVIDIA / AMD / Intel / Apple discrimination at runtime.
  • Power probe is Linux-only. macOS and Windows return PowerState::Unknown, which callers treat as OnAc.

How this map was generated

Five subagents ran in parallel on 2026/05/09, one per slice. Each read the code under its slice, wrote breadcrumbed markdown with file:line refs, returned an executive summary, a cross-slice dependency list, a public-surface inventory, and a debt list. This master page is the synthesis. The data-flow trace is a separate page that follows the audio bytes from microphone to FTS5 search to MCP read.

Refresh history

  • 2026/05/09 — initial generation. Five slices, 103 pages. Generated against codebase head per git log at the time of capture (most recent commit 3c47000 chore(core): add tuning_log_demo example for live heuristic validation).

When to refresh

Re-run the five-slice generation when any of these is true:

  • A new Rust crate is added or removed from the workspace.
  • A new top-level frontend route or window is added.
  • The schema head moves by more than one migration.
  • A new MCP tool ships.
  • A new top-level Tauri plugin is wired.
  • Any slice's debt section has been materially knocked down.
  • Brand rename lands (a sweep across every page is needed).

The procedure for a refresh is in /home/jake/.claude/projects/-home-jake-Documents-CORBEL-Main/memory/ — search for "architecture-map".