scripts/dogfood-rebrand-drill.sh — end-to-end probe that launches the real
lumotia binary against synthetic legacy magnotia state on disk, then
verifies both migration paths produced the expected outcome:
1. paths.rs: ~/.local/share/magnotia/ -> ~/.local/share/lumotia/, including
magnotia.db -> lumotia.db rename + non-DB companion files carried along
by the directory rename.
2. tauri_app_data_migration.rs: ~/.local/share/uk.co.corbel.magnotia/
copied via atomic staging to ~/.local/share/consulting.corbel.lumotia/,
with legacy preserved as a backup and staging dir cleaned up.
Closes the last gap in Phase A: every other test (paths::tests + storage
integration test + localStorageMigration.test.ts) uses synthetic in-process
state. The drill is the only verification that the real binary's startup
hook calls migrate_legacy_data_dir + migrate_tauri_app_data_dir_with_paths
against real OS path resolution.
Two modes:
(default) Sandbox: HOME=<tempdir>, faithful on Linux. NOT
faithful on macOS — Tauri 2 uses
NSSearchPathForDirectoriesInDomains which ignores
HOME overrides. Drill refuses to start in sandbox
mode on macOS rather than silently writing to the
user's real Application Support tree.
--against-real-home Real $HOME. Refuses to start if any lumotia data
already exists at the real paths (no clobbering
real user data). Cleans up planted state on exit
unless --keep is passed.
Eight probes covering: data-dir rename outcome, db file rename, legacy
removal, companion file survival, Tauri app_data_dir copy, legacy-backup
preservation, staging-dir cleanup, and lumotia_startup log line presence.
README: documents the drill alongside cargo test + npm test in the
Testing section, with the macOS caveat clearly flagged.
Not run as part of this commit — the drill launches a Tauri WebView
window for a few seconds. Jake to invoke when ready to dogfood.
426 lines
25 KiB
Markdown
426 lines
25 KiB
Markdown
# Lumotia
|
||
|
||
*Think out loud. Keep working.*
|
||
|
||
Lumotia is a local-first, cognitive-load-aware dictation and task-capture desktop app. Every transcription, LLM cleanup, and task extraction runs on the user's machine. No telemetry, no analytics, no cloud dependency. The app is designed around a single observation: people who think in bursts lose ideas faster than they can type, and the tool's job is to get out of the way.
|
||
|
||
---
|
||
|
||
## Status
|
||
|
||
**Pre-alpha.** Actively dogfooded on Linux (KDE Plasma 6 on Wayland). macOS and Windows targets are in scope and exercised by CI, but not yet beta-ready. One primary user; open source-intent with licence TBD before public beta.
|
||
|
||
- Current `main`: see commit log
|
||
- 9 library crates plus the Tauri app crate; 220+ lib tests plus 67 Tauri-app tests, all passing
|
||
- Cross-platform CI (Linux / macOS / Windows) via GitHub Actions
|
||
- Tracked limitations live in [`KNOWN-ISSUES.md`](KNOWN-ISSUES.md)
|
||
|
||
---
|
||
|
||
## Design principles (non-negotiable)
|
||
|
||
1. **Local-first is the floor, not a feature.** No voice, transcript, or task ever leaves the user's machine unless they explicitly send it. No telemetry.
|
||
2. **Cognitive load is the limiting resource.** Every new setting must earn its mental real estate. Every interaction should reduce, not add, decisions.
|
||
3. **Composable, not monolithic.** Lumotia is a dictation primitive: via MCP, CLI, and filesystem export, it slots into whatever workflow the user already has (Obsidian, Claude Desktop, Cline, any text field).
|
||
4. **LLM scope is narrow.** The in-app LLM does transcription cleanup and task extraction. It is not a wake-word agent, not a chat UI, not a multi-provider cloud fan-out.
|
||
5. **Raw transcript is always recoverable.** Cleanup is additive, never destructive. The user can always see and revert to what Whisper heard.
|
||
|
||
These are enforced in the codebase (where practical) and in the docs under [`docs/whisper-ecosystem/lumotia-context.md`](docs/whisper-ecosystem/lumotia-context.md).
|
||
|
||
---
|
||
|
||
## What Lumotia does today
|
||
|
||
### Speech-to-text
|
||
- Vulkan-accelerated local **Whisper** inference via [whisper-rs](https://github.com/tazz4843/whisper-rs) 0.16 + whisper.cpp. Works on NVIDIA, AMD, Intel Arc, Apple (via MoltenVK), and integrated graphics.
|
||
- Vulkan / CUDA-accelerated **Parakeet** inference via sherpa-onnx (NVIDIA's English-only model; lower latency than Whisper-Large on English).
|
||
- **Six Whisper variants** shipped: Tiny, Base, Small, Distil-Small, Medium, Distil-Large v3.
|
||
- **Parakeet-as-default for English** when hardware supports it; first-run hardware probe picks the fastest-accurate pair.
|
||
- **Resumable downloads with SHA-256 verification**; retains audio if transcription fails.
|
||
- **Per-profile custom vocabulary** fed to Whisper as `initial_prompt` plus to the LLM cleanup prompt; bulk import via paste.
|
||
- **Live streaming transcription** with speech-gated chunking, hallucination filtering, and duplicate-boundary detection.
|
||
|
||
### LLM formatting (local only)
|
||
- Local LLM runtime via [llama-cpp-2](https://github.com/utilityai/llama-cpp-rs) 0.1.144 with Vulkan.
|
||
- Four Qwen tiers (Qwen3.5 2B / 4B / 9B + Qwen3.6 27B) auto-selected by hardware probe.
|
||
- GBNF grammar-constrained output for task extraction (always-parseable JSON).
|
||
- System prompt hardened against voice-delivered prompt injection.
|
||
|
||
### Task capture
|
||
- Automatic task extraction from any transcript.
|
||
- **MicroSteps** — one-tap "break this task into 3–7 concrete physical actions."
|
||
- Profile-scoped task lists with inbox / today / soon / later buckets.
|
||
- Tasks back-link to their source transcript.
|
||
|
||
### Input, paste, and window management
|
||
- **Global hotkey** — evdev-based on Linux (Wayland-compatible out of the box), `tauri-plugin-global-shortcut` on macOS / Windows. Per-OS capability matrix rejects invalid key combinations.
|
||
- **Platform-aware paste matrix** — `wtype` / `xdotool` / `ydotool` on Linux, AppleScript on macOS, SendKeys on Windows. Clipboard snapshot + 300 ms restore after paste.
|
||
- **Wayland-hardened transcription preview overlay** (`/preview`): pinned across virtual desktops, hidden from Alt+Tab via `WindowTypeHint::Utility`, never steals focus, focus-gated open.
|
||
- **Meeting auto-capture** (opt-in, default off): single-signal process-list watcher, user-editable app list, surfaces a non-modal reminder. No mic-activity heuristics, no calendar integration.
|
||
|
||
### History and search
|
||
- **FTS5-indexed transcript search** over SQLite.
|
||
- **YAML-frontmatter markdown export** one-click into Obsidian vault.
|
||
- Per-transcript metadata: starred, manual tags, template, language, duration.
|
||
- Transcript editor window (`/viewer`) with debounced autosave.
|
||
|
||
### External integration
|
||
- **MCP stdio server** (`lumotia-mcp`) exposing read-only transcripts and tasks to any Model Context Protocol client (Claude Desktop, Cline, Cursor, etc.). No authentication, read-only, local-only.
|
||
|
||
### Accessibility
|
||
- Dyslexia-friendly fonts bundled: Lexend, Atkinson Hyperlegible Next, OpenDyslexic.
|
||
- Bionic reading mode.
|
||
- Per-region font size, letter spacing, line height, transcript-specific sizing.
|
||
- System-aware reduce-motion.
|
||
- **i18n**: English, Spanish, German (svelte-i18n scaffold).
|
||
|
||
### Privacy, deployment, reliability
|
||
- Zero telemetry. Zero analytics. No crash reports leave the machine unless explicitly bundled.
|
||
- Auto-update via Tauri updater plugin (signed, user-approved).
|
||
- Per-window size + position persistence (`tauri-plugin-window-state`).
|
||
- Crash + panic capture stored locally; user-bundleable for support.
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
Lumotia is a Tauri 2 desktop app with three layers:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Svelte 5 frontend (src/) │
|
||
│ Routes: /, /float, /viewer, /preview │
|
||
│ Stores, i18n, Tailwind CSS │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ Tauri 2 runtime (src-tauri/) │
|
||
│ Commands: audio, clipboard, diagnostics, feedback, fs, │
|
||
│ hardware, hotkey, intentions, live, llm, meeting, │
|
||
│ models, nudges, paste, profiles, rituals, tasks, │
|
||
│ transcription, transcripts, tts, update, windows │
|
||
│ Utility modules (no commands): mod, power, security │
|
||
│ Plugins: global-shortcut, dialog, opener, updater, │
|
||
│ window-state │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ Rust workspace (crates/) │
|
||
│ lumotia-core, lumotia-audio, lumotia-transcription, lumotia-llm, │
|
||
│ lumotia-ai-formatting, lumotia-storage, lumotia-hotkey, │
|
||
│ lumotia-cloud-providers, lumotia-mcp │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
The Rust workspace is the brain; Tauri is the OS integration surface; Svelte is the UI. The MCP server (`lumotia-mcp`) is a separate binary that opens Lumotia's SQLite store read-only — it's Lumotia-as-primitive for external agents.
|
||
|
||
### Repository layout
|
||
|
||
```
|
||
lumotia/
|
||
├── Cargo.toml # workspace root
|
||
├── src-tauri/ # Tauri app (main binary + commands)
|
||
│ ├── src/
|
||
│ │ ├── commands/ # 22 Tauri command modules + 3 utility modules (`mod`, `power`, `security`)
|
||
│ │ ├── lib.rs # app entry, setup, command registration
|
||
│ │ ├── tray.rs
|
||
│ │ └── main.rs
|
||
│ ├── capabilities/ # Tauri ACL capability files
|
||
│ ├── gen/schemas/ # auto-generated ACL schemas
|
||
│ ├── tauri.conf.json # base Tauri config
|
||
│ ├── tauri.linux.conf.json # Linux overlay (native decorations)
|
||
│ └── resources/windows/ # Windows-specific bundled assets
|
||
├── crates/ # workspace Rust crates
|
||
│ ├── ai-formatting/ # post-processing pipeline + LLM cleanup client
|
||
│ ├── audio/ # capture, resampling, decoding, WAV I/O
|
||
│ ├── cloud-providers/ # BYOK cloud STT stubs (empty scaffolding)
|
||
│ ├── core/ # types, hardware probe, model registry, process watch
|
||
│ ├── hotkey/ # Linux evdev hotkey listener
|
||
│ ├── llm/ # llama-cpp-2 engine + model manager
|
||
│ ├── mcp/ # MCP stdio server binary
|
||
│ ├── storage/ # SQLite + FTS5 + file storage
|
||
│ └── transcription/ # Whisper + Parakeet wrappers, model mgmt
|
||
├── src/ # Svelte frontend
|
||
│ ├── routes/ # SvelteKit routes
|
||
│ │ ├── +page.svelte # main dictation UI
|
||
│ │ ├── +layout.svelte # shell (sidebar, tray sync, hotkey wiring)
|
||
│ │ ├── float/ # tasks float window
|
||
│ │ ├── viewer/ # transcript editor window
|
||
│ │ └── preview/ # transcription preview overlay
|
||
│ ├── lib/
|
||
│ │ ├── pages/ # DictationPage, SettingsPage, HistoryPage, TasksPage, FilesPage, FirstRunPage
|
||
│ │ ├── components/ # reusable Svelte components
|
||
│ │ ├── stores/ # $state stores (page, preferences, profiles, toasts)
|
||
│ │ ├── actions/ # Svelte actions (bionic reading, etc.)
|
||
│ │ ├── utils/ # frontmatter, textMeasure, errors, storage helpers
|
||
│ │ ├── types/ # TS type definitions
|
||
│ │ └── i18n/ # svelte-i18n setup + en/es/de locales
|
||
│ ├── fonts/ # bundled accessibility fonts
|
||
│ ├── design-system/ # design tokens + UI kit references (not live code)
|
||
│ └── app.css
|
||
├── docs/ # all project documentation (see below)
|
||
├── .github/workflows/ # CI (check.yml, build.yml)
|
||
├── package.json
|
||
├── HANDOVER.md # latest session handover
|
||
└── run.sh # dev launcher (starts Vite then Tauri)
|
||
```
|
||
|
||
### Rust crates
|
||
|
||
| Crate | Responsibility |
|
||
|---|---|
|
||
| **`lumotia-core`** | Shared types (`Segment`, `Transcript`, `Megabytes`, `ModelId`), constants, the `Engine` / `SpeedTier` / `AccuracyTier` enums, hardware probe (`sysinfo`-based), model registry (Whisper + Parakeet entries), hardware-aware recommendation scoring, `process_watch` for meeting detection. |
|
||
| **`lumotia-audio`** | `cpal`-based microphone capture with device hotplug + error forwarding, VAD, `rubato` streaming resampler to 16 kHz mono, `symphonia` file decoding, `hound` WAV I/O. |
|
||
| **`lumotia-transcription`** | `whisper-rs` backend (`WhisperRsBackend`) that owns a `WhisperContext` and supports `set_initial_prompt`. `LocalEngine` wraps both Whisper and Parakeet (via `transcribe-rs` ONNX) behind a common `Transcriber` trait. Streaming primitives (`VadChunker`, `LocalAgreement`, buffer trim) live in the `streaming/` module. Model manager handles downloads, paths, and disk checks. |
|
||
| **`lumotia-llm`** | `llama-cpp-2` engine with a four-tier Qwen3.5 / Qwen3.6 model manager. Three high-level surfaces: `cleanup_text` (formatting), `decompose_task` (3–7 micro-steps, GBNF-constrained JSON array), `extract_tasks` (optional-array, GBNF-constrained). Resumable HTTP downloads with SHA-256 verify. |
|
||
| **`lumotia-ai-formatting`** | Post-processing pipeline: filler removal, British English conversion, anti-hallucination filter, smart paragraph breaks on long pauses, optional LLM cleanup. Also hosts the `llm_client::CLEANUP_PROMPT` constant (prompt-injection-hardened). |
|
||
| **`lumotia-storage`** | SQLite via `sqlx` 0.8. Migrations, CRUD for transcripts / tasks / subtasks / profiles / profile terms / settings / error log, FTS5 search, file-storage paths. |
|
||
| **`lumotia-hotkey`** | Linux `evdev` hotkey listener with device hotplug. Parses Tauri-style hotkey strings (`Ctrl+Shift+R`), emits Pressed / Released events. Works natively on Wayland (no X11 dependency). Checks `/dev/input/event*` access on startup; surfaces a clear "add yourself to the `input` group" error when missing. |
|
||
| **`lumotia-cloud-providers`** | BYOK cloud-STT provider stubs. Currently empty scaffolding. When populated: OpenAI-compatible endpoint + Anthropic (ceiling for scope). |
|
||
| **`lumotia-mcp`** | Standalone `lumotia-mcp` binary implementing the MCP stdio protocol (2024-11-05). Read-only tools: `list_transcripts`, `get_transcript`, `search_transcripts`, `list_tasks`. Opens Lumotia's SQLite store. |
|
||
|
||
### Tauri commands (src-tauri/src/commands/)
|
||
|
||
| Module | What it exposes |
|
||
|---|---|
|
||
| `audio` | Device enumeration, native capture start/stop, audio-samples persistence |
|
||
| `clipboard` | Cross-platform clipboard write (arboard) |
|
||
| `diagnostics` | Panic hook, frontend error log, crash file listing, diagnostic report bundler |
|
||
| `feedback` | Thumbs / correction capture on AI-generated output; few-shot example store for prompt conditioning |
|
||
| `fs` | Thin filesystem write for the OS save-dialog path (UTF-8 text, dialog-constrained) |
|
||
| `hardware` | `probe_system`, `rank_models` |
|
||
| `hotkey` | `start_evdev_hotkey`, `update_evdev_hotkey`, `stop_evdev_hotkey`, `check_hotkey_access`, `is_wayland_session` |
|
||
| `intentions` | Implementation-intention rule CRUD (if-then automation: time-of-day, task-completed, morning-triage triggers) |
|
||
| `live` | Live streaming transcription session lifecycle + speech-gate tuning |
|
||
| `llm` | Tier recommend, model check / download / load / unload / delete, status, `cleanup_transcript_text_cmd`, `extract_tasks_from_transcript_cmd` |
|
||
| `meeting` | `detect_meeting_processes` (process-list poll) |
|
||
| `models` | Whisper + Parakeet model download / load / check / default-id resolution, runtime capabilities API, pre-warm |
|
||
| `nudges` | Margot soft-touch nudge delivery via `tauri-plugin-notification`; main-window-only guard |
|
||
| `paste` | `paste_text` (copy + keystroke), `detect_paste_backends`, Wayland focus-race mitigation against the preview overlay |
|
||
| `profiles` | Profile CRUD, profile-terms CRUD, learn-terms-from-edit |
|
||
| `rituals` | Start- and shutdown-ritual sentinels (last-shown date for the morning-triage modal) |
|
||
| `tasks` | Task CRUD, subtask CRUD, `decompose_and_store`, `extract_tasks_from_transcript_cmd` |
|
||
| `transcription` | `transcribe_pcm`, `transcribe_file`, `transcribe_pcm_parakeet` |
|
||
| `transcripts` | Transcript CRUD + FTS5 search |
|
||
| `tts` | Platform-native Read Page Aloud (`spd-say` / `say` / PowerShell), with cancellable child-process tracking |
|
||
| `update` | Tauri-plugin-updater check / install |
|
||
| `windows` | `open_task_window`, `open_viewer_window`, `open_preview_window`, `close_preview_window` |
|
||
|
||
Utility modules in the same directory (no `#[tauri::command]` attributes; helpers consumed by the command modules above): `mod` (registry), `power` (macOS `PowerAssertion` guard against App Nap during long sessions), `security` (`ensure_main_window` guard).
|
||
|
||
### Frontend (src/)
|
||
|
||
- **SvelteKit + Svelte 5 runes** (`$state`, `$derived`, `$effect`).
|
||
- **Tailwind CSS 4** for styling, with a Lexend/Atkinson/OpenDyslexic type system.
|
||
- **Secondary windows** (`/float`, `/viewer`, `/preview`) use named layouts (`+layout@.svelte`) to skip the main shell and run chrome-free.
|
||
- **Reactive stores** (`src/lib/stores/`, one file per store): `page.svelte.ts` (central app state; transcripts, profiles, taskLists, templates, etc. live as fields here), `preferences.svelte.ts`, `profiles.svelte.ts`, `toasts.svelte.ts`, `focusTimer.svelte.ts`, `llmStatus.svelte.ts`, `nudgeBus.svelte.ts`, `implementationIntentions.svelte.ts`, `completionStats.svelte.ts`, `speaker.svelte.ts`.
|
||
- **i18n**: `svelte-i18n` with en/es/de locales at `src/lib/i18n/locales/`. Scaffolding only — strings migrate to translation keys incrementally.
|
||
|
||
---
|
||
|
||
## Runtime stack
|
||
|
||
| Layer | Technology | Version |
|
||
|---|---|---|
|
||
| Desktop framework | [Tauri](https://tauri.app) | 2.10.3 |
|
||
| Frontend | Svelte 5 + SvelteKit + Vite | latest |
|
||
| Styling | Tailwind CSS | 4.x |
|
||
| Speech-to-text (primary) | whisper.cpp via [`whisper-rs`](https://github.com/tazz4843/whisper-rs) | 0.16 (Vulkan feature) |
|
||
| Speech-to-text (Parakeet) | sherpa-onnx via `transcribe-rs` | 0.3 |
|
||
| Local LLM | [`llama-cpp-2`](https://github.com/utilityai/llama-cpp-rs) | 0.1.144 (openmp + vulkan) |
|
||
| Database | SQLite via [`sqlx`](https://github.com/launchbadge/sqlx) | 0.8 |
|
||
| Async runtime | [`tokio`](https://tokio.rs/) | 1.x |
|
||
| Audio capture | [`cpal`](https://github.com/RustAudio/cpal) | current |
|
||
| Resampling | [`rubato`](https://github.com/HEnquist/rubato) | current |
|
||
| File decode | [`symphonia`](https://github.com/pdeljanov/Symphonia) | current |
|
||
|
||
---
|
||
|
||
## Platform support
|
||
|
||
| Platform | Status | Notes |
|
||
|---|---|---|
|
||
| Linux Wayland (KDE Plasma, GNOME Mutter, Hyprland, Sway) | **Primary target**, daily-dogfooded on KDE | evdev hotkey, GTK 3 via webkit2gtk, Vulkan, all paste backends; idle inhibit not wired (see KI-02) |
|
||
| Linux X11 | Supported | xdotool paste path, GTK 3; idle inhibit not wired (see KI-02) |
|
||
| macOS | In CI, untested runtime | osascript paste, Metal via MoltenVK, App Nap guard pending Apple Silicon verification (see KI-01) |
|
||
| Windows | In CI, untested runtime | SendKeys paste, Vulkan-first GPU path, bundled DLLs for CPU fallback; sleep prevention not wired (see KI-03) |
|
||
|
||
CI runs `cargo check --workspace --all-targets` + `svelte-check` on all three on every push and PR.
|
||
|
||
---
|
||
|
||
## Build + development
|
||
|
||
### Prerequisites
|
||
|
||
Linux (Fedora/RHEL listed; adjust for your distro):
|
||
```
|
||
sudo dnf install libclang-devel clang \
|
||
webkit2gtk4.1-devel libappindicator-gtk3-devel librsvg2-devel \
|
||
alsa-lib-devel systemd-devel cmake \
|
||
vulkan-headers vulkan-loader-devel glslc
|
||
```
|
||
|
||
macOS:
|
||
```
|
||
brew install cmake llvm vulkan-headers vulkan-loader molten-vk shaderc
|
||
```
|
||
|
||
Windows:
|
||
```
|
||
choco install cmake llvm vulkan-sdk
|
||
```
|
||
|
||
See [`docs/dev-setup.md`](docs/dev-setup.md) for the authoritative per-platform dependency list and for how `LIBCLANG_PATH` should be set.
|
||
|
||
### Installing npm dependencies
|
||
|
||
Use `npm ci --ignore-scripts` rather than bare `npm install`. `--ignore-scripts` blocks the postinstall script vector that npm-worm attacks (Shai-Hulud, mini-Shai-Hulud) rely on. `ci` installs strictly from `package-lock.json`, refusing to mutate the lockfile silently.
|
||
|
||
```bash
|
||
npm ci --ignore-scripts
|
||
```
|
||
|
||
`run.sh` runs `npm audit signatures` automatically whenever `package-lock.json` is newer than the last successful audit, and refuses to launch on signature mismatch. Skip with `LUMOTIA_SKIP_AUDIT=1` for offline dev.
|
||
|
||
### Dev launch
|
||
|
||
Canonical full-stack dev launch — starts Vite, waits for port 1420, then launches Tauri:
|
||
|
||
```bash
|
||
npm run dev:tauri
|
||
```
|
||
|
||
Direct shell equivalent:
|
||
|
||
```bash
|
||
./run.sh
|
||
```
|
||
|
||
For pure frontend iteration without Tauri:
|
||
|
||
```bash
|
||
npm run dev:frontend
|
||
```
|
||
|
||
### Build
|
||
|
||
```bash
|
||
npm run tauri build # release build, produces .AppImage / .deb / .dmg / .msi / .exe
|
||
```
|
||
|
||
CI also builds release installers on tag push (see `.github/workflows/build.yml`).
|
||
|
||
### Testing
|
||
|
||
```bash
|
||
cargo test --workspace # all Rust tests (lib + integration)
|
||
npm run check # svelte-check (type-checks .svelte files)
|
||
npm run test # vitest run (frontend unit tests)
|
||
npm run test:watch # vitest watch mode
|
||
cargo check --workspace --all-targets
|
||
```
|
||
|
||
Frontend test files live alongside source (`src/**/*.test.ts`) and run in
|
||
jsdom by default. See [vite.config.js](vite.config.js) for the vitest
|
||
configuration.
|
||
|
||
#### Rebrand-migration dogfood drill
|
||
|
||
End-to-end probe that launches the real `target/debug/lumotia` binary
|
||
against synthetic legacy magnotia state planted on disk, then verifies
|
||
both migration paths produced the expected on-disk outcome.
|
||
|
||
```bash
|
||
cargo build -p lumotia # need the binary first
|
||
scripts/dogfood-rebrand-drill.sh # sandbox mode (Linux only)
|
||
scripts/dogfood-rebrand-drill.sh --keep # leave sandbox dir for inspection
|
||
scripts/dogfood-rebrand-drill.sh --against-real-home # run against real $HOME
|
||
```
|
||
|
||
Sandbox mode is faithful only on Linux — Tauri 2 on macOS uses
|
||
`NSSearchPathForDirectoriesInDomains` which ignores `HOME` overrides. The
|
||
drill refuses to start in sandbox mode on macOS. Real-home mode refuses
|
||
to start if any lumotia data already exists at your real paths, so it
|
||
can roll back cleanly on exit.
|
||
|
||
---
|
||
|
||
## Project documentation
|
||
|
||
Beyond this README, the repo ships extensive internal documentation:
|
||
|
||
### Product + strategy — `docs/brief/`
|
||
Research briefs, competitive analysis, and strategic framing. Start with:
|
||
- [`what-lumotia-is.md`](docs/brief/what-lumotia-is.md) — product thesis
|
||
- [`why-current-tools-fail.md`](docs/brief/why-current-tools-fail.md) — market gap
|
||
- [`design-principles.md`](docs/brief/design-principles.md) — full principle list
|
||
- [`target-audience.md`](docs/brief/target-audience.md), [`market-size-demographics.md`](docs/brief/market-size-demographics.md)
|
||
- Appendices on cognitive ergonomics, AI body doubling, evolutionary psychology, implementation intentions, HITL scaffolding, voice interfaces
|
||
|
||
### Brand — `docs/brand/`
|
||
- [`lumotia-brand-guidelines.md`](docs/brand/lumotia-brand-guidelines.md)
|
||
- [`lumotia-brand-platform.md`](docs/brand/lumotia-brand-platform.md)
|
||
|
||
### Technical research — `docs/whisper-ecosystem/`
|
||
Cross-repo survey of 10 OSS Whisper projects, the Lumotia-specific atomic task backlog, and the two Cursor workstream plans.
|
||
- [`brief.md`](docs/whisper-ecosystem/brief.md) — 31-item task backlog (the canonical research spec)
|
||
- [`lumotia-context.md`](docs/whisper-ecosystem/lumotia-context.md) — ideology, shipped state, file-ownership fence for cloud AI agents
|
||
- [`workstream-A.md`](docs/whisper-ecosystem/workstream-A.md), [`workstream-B.md`](docs/whisper-ecosystem/workstream-B.md) — executed workstream plans
|
||
|
||
### GPU tuning — `docs/gpu-tuning/`
|
||
- [`plan.md`](docs/gpu-tuning/plan.md) — MVP plan for GGML env-var panel + `lumotia-bench` auto-tuner + `lumotia-configs` community repo
|
||
|
||
### Session handovers
|
||
- [`HANDOVER.md`](HANDOVER.md) — latest session summary
|
||
- Dated historical handovers under [`docs/handovers/`](docs/handovers/): `HANDOVER-2026-04-17.md`, `HANDOVER-2026-04-18.md`, `HANDOVER-2026-04-19.md`, `HANDOVER-2026-04-24.md`
|
||
|
||
### Dev reference
|
||
- [`docs/dev-setup.md`](docs/dev-setup.md) — dependency + launch reference
|
||
- [`docs/icon-mapping.md`](docs/icon-mapping.md) — icon conventions
|
||
- [`KNOWN-ISSUES.md`](KNOWN-ISSUES.md) — tracked partial implementations and limitations
|
||
|
||
---
|
||
|
||
## Roadmap
|
||
|
||
The shipped code represents Phases 1–3 and a partial Phase 4.
|
||
|
||
Pinned roadmap items (scoped in docs and session memory):
|
||
|
||
- **Phase 4** — remaining items from [`workstream-A.md`](docs/whisper-ecosystem/workstream-A.md) + [`workstream-B.md`](docs/whisper-ecosystem/workstream-B.md)
|
||
- **Voice calibration** — three-tier plan replacing the hardcoded speech-gate with per-user baselines
|
||
- **GPU community tuning** — see [`docs/gpu-tuning/plan.md`](docs/gpu-tuning/plan.md); five-phase roadmap from settings panel to agentic auto-tuner + community config repo
|
||
- **Cloud endpoint contract test** — when `lumotia-cloud-providers` grows a real provider
|
||
- **`ggml` dedup** — replace the interim `-Wl,--allow-multiple-definition` link flag with a proper shared-lib setup; unblocks custom shader / backend work
|
||
- **Mobile (iOS / Android)** — long-horizon, gated on the single-binary Rust stack scaling
|
||
|
||
Explicitly shelved (not coming without specific community signal):
|
||
- Wake-word / always-listening agent
|
||
- Chat-style LLM UI
|
||
- Multi-provider cloud fan-out beyond OpenAI-compatible + Anthropic
|
||
- Second notes-editing surface (transcripts leave Lumotia via frontmatter to Obsidian)
|
||
- Speaker diarization
|
||
- Dragon-style passage-based speaker fine-tuning (Whisper has no speaker adaptation)
|
||
|
||
---
|
||
|
||
## Contributing
|
||
|
||
Pre-alpha status; contribution process TBD before public beta. For now:
|
||
|
||
- Every Tauri command change must register in both [`src-tauri/src/lib.rs`](src-tauri/src/lib.rs) (invoke handler) and in the invoking frontend code.
|
||
- Every Settings-visible setting must have a type field in [`src/lib/types/app.ts`](src/lib/types/app.ts) and a default in [`src/lib/stores/page.svelte.ts`](src/lib/stores/page.svelte.ts).
|
||
- Every new workspace crate needs a `description` in its `Cargo.toml`.
|
||
- Tests: add at least a smoke test per new Tauri command or crate module. The workspace test floor is "no regressions on main."
|
||
- Wayland compatibility is a first-class concern — don't assume X11. The preview overlay and paste matrix live-document what this looks like in practice.
|
||
|
||
---
|
||
|
||
## Licence
|
||
|
||
To be finalised before public beta. Current intent: MIT or similar permissive licence, with Corbel Consulting offering optional commercial support / managed services as the revenue path.
|
||
|
||
---
|
||
|
||
## Contact
|
||
|
||
**Jake Sames** — [jakeadriansames@gmail.com](mailto:jakeadriansames@gmail.com)
|
||
Repo: [github.com/jakejars/lumotia](https://github.com/jakejars/lumotia) · [git.corbel.consulting/jake/lumotia](https://git.corbel.consulting/jake/lumotia)
|