Files
Lumotia/docs/audit/phase0-cartography.md
Claude 0b6be94f3e docs(audit): add Phase 0 cartography report
Inventory of workspace shape, LOC, dependency graph, public API surface,
external surfaces (Tauri commands / MCP tools / frontend routes), and a
README↔code drift log. Input for Phase 1 (lean-pass).

Surfaces five concrete README drifts (one HIGH: stores list fiction; two
MED: undocumented Tauri modules and a Moonshine claim with no registry
entry) and three structural smells worth a Phase-2 follow-up.
2026-04-30 14:51:18 +00:00

236 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 0 — Cartography
*Acquisition-grade audit, Phase 0 deliverable. Date: 2026-04-30. Branch: `claude/rebrand-to-magnotia-UWYkg`.*
This is a survey, not a verdict. It maps what exists, sizes the surface, and flags every place the README disagrees with the code. Phase 1 (lean-pass) and Phase 2 (architecture conformance) consume this as input.
---
## 1. Workspace shape
| Layer | Path | Notes |
|---|---|---|
| Rust workspace root | `Cargo.toml` | `members = ["src-tauri", "crates/*"]`, `resolver = "2"` |
| Tauri app crate | `src-tauri/` | Library `magnotia_lib` + binary `magnotia` |
| Library crates | `crates/*` (×9) | See §3 |
| MCP standalone binary | `crates/mcp/` | Bin `magnotia-mcp` (separate process from main app) |
| Svelte frontend | `src/` | SvelteKit, Svelte 5 runes, Tailwind 4 |
| Static assets | `static/`, `src-tauri/icons/`, `src-tauri/resources/` | |
**Binaries shipped (2):** `magnotia` (Tauri app), `magnotia-mcp` (stdio MCP server).
---
## 2. Lines of code
| Area | LOC | Files |
|---|---:|---:|
| `crates/` (Rust, all 9 crates) | 13,261 | 52 |
| `src-tauri/` (Rust) | 8,330 | 27 |
| Frontend (Svelte/TS/JS, excl. design-system) | 15,192 | ~80 |
| `src/design-system/` (reference kit, not live code) | 1,412 | — |
| **Total active** | **~36,800** | |
### Largest files (top complexity candidates)
| LOC | File |
|---:|---|
| 2,534 | `crates/storage/src/database.rs` |
| 2,250 | `src/lib/pages/SettingsPage.svelte` |
| 1,737 | `src-tauri/src/commands/live.rs` |
| 1,185 | `crates/storage/src/migrations.rs` |
| 1,081 | `src/lib/pages/DictationPage.svelte` |
| 897 | `src/lib/pages/HistoryPage.svelte` |
| 790 | `src-tauri/src/commands/paste.rs` |
| 735 | `crates/transcription/src/streaming/rms_vad.rs` |
| 725 | `src/lib/pages/TasksPage.svelte` |
| 720 | `src-tauri/src/commands/models.rs` |
| 697 | `src/lib/stores/page.svelte.ts` |
> **Phase 1 candidate.** `database.rs` (2.5k), `SettingsPage.svelte` (2.25k), and `live.rs` (1.7k) are each large enough to deserve a structural review in isolation. HANDOVER.md already flags `SettingsPage` as needing decomposition into 7 progressive-disclosure groups.
---
## 3. Crate inventory
| Crate | LOC | Files | `pub` items (lib.rs / total) | Tests |
|---|---:|---:|---:|---:|
| `magnotia-core` | 1,212 | 9 | 10 / 104 | 16 |
| `magnotia-audio` | 1,533 | 8 | 14 / 38 | 14 |
| `magnotia-transcription` | 2,617 | 12 | 13 / 51 | 51 |
| `magnotia-llm` | 1,330 | 6 | 27 / 56 | 17 |
| `magnotia-ai-formatting` | 1,502 | 6 | 9 / 21 | 47 |
| `magnotia-storage` | 3,771 | 4 | 6 / 69 | 60 |
| `magnotia-hotkey` | 632 | 3 | 5 / 14 | 4 |
| `magnotia-cloud-providers` | 80 | 2 | 2 / 3 | 2 |
| `magnotia-mcp` | 584 | 2 | 8 / 8 | 9 |
| `src-tauri` (`magnotia` + `magnotia_lib`) | 8,330 | 27 | n/a | 67 |
| **Total** | **21,591** | | | **287** |
**Outliers worth a Phase-2 look:**
- `magnotia-core` exposes 104 public items — high for a "shared types" crate; likely leakage of internals.
- `magnotia-storage` exposes 69 public items across only 4 files; the file split is suspect (2.5k-line `database.rs`).
- `magnotia-cloud-providers` is 80 LOC and 3 public items — README calls it "empty scaffolding" (verified: just an in-memory keystore + env-var fallback). Either grow it or remove it; it currently earns nothing.
---
## 4. Crate dependency graph
```
magnotia-core ──┬─→ magnotia-audio
├─→ magnotia-transcription
├─→ magnotia-llm ──→ magnotia-ai-formatting
├─→ magnotia-cloud-providers
├─→ magnotia-hotkey
└─→ magnotia-storage ──→ magnotia-mcp
magnotia (src-tauri)
└─→ all 8 library crates (NOT magnotia-mcp — separate binary)
```
**Observations:**
- `magnotia-core` is the workspace floor; nothing depends on it depending on something else. Good.
- DAG is clean — no cycles, no upward dependencies.
- `magnotia-mcp` correctly depends only on `magnotia-storage` (its sole job is to read the SQLite DB). The Tauri app does **not** depend on it, confirming the "separate process" claim in the README.
- `magnotia-ai-formatting` depends on both `core` and `llm`. Reasonable.
> **Phase 2 will verify:** every `pub` item in the leaf crates (`audio`, `transcription`, `llm`, `storage`, `hotkey`) has at least one external consumer. Internal-only items shouldn't be `pub`.
---
## 5. External surfaces
### 5.1 Tauri commands
**102 `#[tauri::command]` attributes** across **22 of 25** modules in `src-tauri/src/commands/`.
- `power.rs` and `security.rs` are utility modules (no commands; helpers only).
- `mod.rs` is the registry.
| Module | # commands | Module | # commands |
|---|---:|---|---:|
| `tasks` | 12 | `intentions` | 5 |
| `models` | 12 | `audio` | 4 |
| `llm` | 10 | `tts` | 3 |
| `profiles` | 9 | `transcription` | 3 |
| `transcripts` | 8 | `paste` | 3 |
| `windows` | 8 | `update` | 2 |
| `diagnostics` | 6 | `rituals` | 2 |
| `hotkey` | 5 | `live` | 2 |
| | | `hardware` | 2 |
| | | `feedback` | 2 |
| | | `nudges`, `meeting`, `fs`, `clipboard` | 1 each |
**Every one of these is a trust boundary** — Phase 4 (security) will audit input validation per command.
### 5.2 MCP tools (read-only stdio)
Confirmed in `crates/mcp/src/lib.rs`:
- `list_transcripts`
- `get_transcript`
- `search_transcripts`
- `list_tasks`
The `init_readonly` connection mode in `magnotia-storage` is opened at OS level (`SQLITE_OPEN_READONLY`), per `crates/mcp/src/main.rs:18` — Phase 4 will confirm with a write-attempt test.
### 5.3 Frontend route surface
| Route | Purpose | Layout |
|---|---|---|
| `/` | Main dictation shell | `+layout.svelte` (sidebar + chrome) |
| `/float` | Tasks float window | `+layout@.svelte` (chrome-free) |
| `/viewer` | Transcript editor | `+layout@.svelte` (chrome-free) |
| `/preview` | Live transcription overlay | `+layout@.svelte` (chrome-free) |
**Pages:** `DictationPage`, `SettingsPage`, `HistoryPage`, `TasksPage`, `FilesPage`, `FirstRunPage`, `ShutdownRitualPage` (7).
**Stores:** `page`, `preferences`, `profiles`, `toasts`, `focusTimer`, `llmStatus`, `nudgeBus`, `implementationIntentions`, `completionStats`, `speaker` (10).
**Components:** 25 in `src/lib/components/`.
**i18n locales:** `en`, `es`, `de` (scaffolding only — most strings are still hard-coded; the migration is incremental per README).
### 5.4 Model registry
7 models declared in `crates/core/src/model_registry.rs`:
- Whisper (6): `whisper-tiny-en`, `whisper-base-en`, `whisper-small-en`, `whisper-distil-small-en`, `whisper-medium-en`, `whisper-distil-large-v3`
- Parakeet (1): `parakeet-ctc-0.6b-int8`
> Moonshine is mentioned in the README's `magnotia-core` description ("Moonshine entries") but **no Moonshine entry exists in the registry**. See §7.
---
## 6. Test floor
| Location | Count |
|---|---:|
| `crates/*/src/` (lib tests) | 217 |
| `crates/*/tests/` (integration) | 3 |
| `src-tauri/src/` + `src-tauri/tests/` | 67 |
| **Total** | **287** |
Only 3 cross-crate integration tests is light. Per-crate lib tests dominate. Phase 5 (test integrity) will mutation-test the heavy crates (`storage`, `transcription`, `llm`) to grade whether these tests actually pin behaviour.
---
## 7. README ↔ code drift
Items where the README disagrees with the code as-of this audit:
| README claim | Reality | Severity |
|---|---|---|
| "245 automated lib tests across 10 crates" (line 14) | **287 tests** total (220 lib + 67 src-tauri); 220 lib-only | LOW — undercount (good direction, but stale) |
| "10 crates" (line 14) | 9 library crates + 1 app crate (`src-tauri`) — depends how you count; technically the workspace has 10 packages | OK if counting `src-tauri`; misleading otherwise |
| "Commands: audio, clipboard, diagnostics, hotkey, live, llm, meeting, models, paste, power, profiles, tasks, transcription, transcripts, update, windows" (line 95-97) — 16 listed | **22 modules with commands**: README missing `feedback`, `fs`, `intentions`, `nudges`, `rituals`, `tts`. Architecture diagram and §"Tauri commands" table both stale. | **MED** — visible to anyone evaluating the codebase |
| "18 Tauri command modules" (line 117) | **25 files** in `commands/` (22 with command attrs + `mod`, `power`, `security`) | MED |
| `magnotia-core` "model registry (Whisper + Parakeet + Moonshine entries)" (line 165) | **No Moonshine entries** in `model_registry.rs`. 6 Whisper + 1 Parakeet only. | **MED** — claims an unimplemented feature |
| Stores listed: `settings, profiles, tasks, history, taskLists, templates, page, toasts, preferences` (line 202) | Actual stores: `page, preferences, profiles, toasts, focusTimer, llmStatus, nudgeBus, implementationIntentions, completionStats, speaker`. README list is **largely fictional** — there is no `tasks`, `history`, `taskLists`, `templates`, or `settings` store as a separate file. | **HIGH** — describes architecture that doesn't exist |
| `magnotia-cloud-providers` "BYOK cloud-STT provider stubs… Currently empty scaffolding. When populated: OpenAI-compatible endpoint + Anthropic" (line 172) | Crate has an in-memory API-key store with env-var fallback — not "empty scaffolding". No HTTP code, no provider implementations. | LOW — partial |
| "Every new workspace crate needs a `description` in its `Cargo.toml`" (line 362, contributing rule) | **`crates/llm/Cargo.toml` has no `description` field.** Self-violation of the contribution rule. | LOW — easy fix |
| README §"Architecture" Rust crate list spelling (line 102-104) | Correct, but the manual line-break formatting got mangled by the rebrand sweep — visible whitespace inconsistency. | TRIVIAL |
> **Phase 0 verdict on documentation truth:** The README is **mostly right but actively misleading in two places** — the stores list and the Moonshine claim. Both will fail an acquirer's first sanity-check (`grep -r "Moonshine" crates/`) and erode trust in the rest of the doc.
---
## 8. HANDOVER files
| File | Date | Topic | Status |
|---|---|---|---|
| `HANDOVER.md` | 2026-04-25 | Latest session (Phase 9a9d) | Active reference |
| `HANDOVER-2026-04-24.md` | 2026-04-24 | Phase 8 close | Historical |
| `HANDOVER-2026-04-19.md` | 2026-04-19 | Earlier session | Historical |
| `HANDOVER-2026-04-18.md` | 2026-04-18 | Earlier session | Historical |
| `HANDOVER-2026-04-17.md` | 2026-04-17 | Earliest in tree | Historical |
Five handovers in the repo root is unusual — most projects keep one. Phase 8 (docs truth) will recommend either archiving them under `docs/handovers/` or rotating to a single `HANDOVER.md` with prior content moved.
The post-rebrand state: all five handovers were rewritten by today's sweep (line counts identical, words different). They now reference `magnotia` paths but their **content** describes work done under the `kon` / `corbie` names — there's a temporal-vs-naming mismatch a reader has to mentally track. Acquirer-friendly fix: add a one-line note at the top of each historical handover saying "Originally written when the product was named X; references rewritten 2026-04-30."
---
## 9. Quick wins surfaced (defer to Phase 1, but worth flagging)
1. **Add `description` to `crates/llm/Cargo.toml`** — 1-line fix; closes a self-imposed contribution-rule violation.
2. **Update README stores list** — replace fiction with reality. See §7.
3. **Remove or implement Moonshine claim** — README, line 165.
4. **Update README Tauri commands list** — six modules undocumented. See §7.
5. **Decide on `magnotia-cloud-providers`** — currently 80 LOC of a keystore that two consumers call. Either fold into `magnotia-core::keystore` (it's not provider-specific) or actually grow it. Right now it's a crate that doesn't earn its existence.
---
## 10. Phase 1 entry plan
Based on this cartography, Phase 1 (Lean-pass) should target — in this order — the highest-value, lowest-risk wins:
1. `cargo machete` + `cargo udeps` workspace-wide → unused deps kill list.
2. `knip` on the frontend → unused TS/Svelte modules.
3. Manual review of the **5 files >1k LOC** for duplicate logic (`SettingsPage.svelte`, `database.rs`, `live.rs`, `migrations.rs`, `DictationPage.svelte`).
4. Grep audit of `TODO` / `FIXME` / `unimplemented!` / `unwrap()` outside tests → tech-debt log.
5. Reconcile the §7 README drifts.
Estimated time: **1 working day** to deliver Phase 1 in full.
---
*End of Phase 0 cartography.*