agent: lumotia-rebrand — docs, scripts, root config, residuals
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

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>
This commit is contained in:
2026-05-13 12:38:03 +01:00
parent 681a9b26dc
commit 26c7307607
213 changed files with 1175 additions and 1170 deletions

View File

@@ -42,14 +42,14 @@ From the Workstream B prompt:
contract. Load-bearing. Any prompt edit that softens it gets
rejected at review.
4. **Local-first.** No feature may assume cloud availability. Ollama
(#27) is additive — Magnotia works fully offline without it.
(#27) is additive — Lumotia works fully offline without it.
---
## Execution order
Three phases, each one commit per concern, each ending with a green
`cargo build -p magnotia && npm run check`. We stop at each phase boundary
`cargo build -p lumotia && npm run check`. We stop at each phase boundary
for review.
### Phase B.1 — Pre-emptive UX (items #3, #4 UX, #5, #10, #11)
@@ -61,11 +61,11 @@ a bug, which matches the brief's "pre-emptive patches" framing.
|---|---|---|---|
| 1 | **#3**: clipboard snapshot + restore after paste | `src-tauri/src/commands/paste.rs` already paste-matrix-hardens for Wayland. Extend it: before `Clipboard::new().set_text(text)`, read the existing `Clipboard::get_text()` snapshot (+ `get_image()` if supported by arboard on this target). Schedule a `tokio::spawn` task that sleeps 300ms after paste and restores the snapshot. User's prior clipboard content is therefore recovered automatically. Keep the `hide_preview_overlay_for_paste` dance. | No |
| 2 | **#4 (UX side)**: debounce hotkey, add "warming up…" state | A warms the CPAL stream at app start. B owns the `page.status` state machine: the hotkey handler in `DictationPage.svelte` already gates on `page.recording`; add a ~120ms debounce on the hotkey press so a rapid double-tap doesn't double-init. Existing native capture path is untouched. | Stream warm-up lands in A's Phase A.3 (item #23); B's debounce is independent. |
| 3 | **#5**: hotkey capability matrix per OS, UI rejection of invalid combos | `src/lib/components/HotkeyRecorder.svelte` (or equivalent). Add `hotkeyValidity.ts` returning `{ valid: boolean, reason: string \| null }` given a combo + OS. Rules: on X11, reject single-key combos and report "Add a modifier to capture this key outside Magnotia"; on Windows, reject combos whose only modifier is a right-hand variant (RCtrl/RAlt — per `Handy` #966); on macOS, reject Fn-only combos. Block save button + surface inline "why" copy. | No |
| 3 | **#5**: hotkey capability matrix per OS, UI rejection of invalid combos | `src/lib/components/HotkeyRecorder.svelte` (or equivalent). Add `hotkeyValidity.ts` returning `{ valid: boolean, reason: string \| null }` given a combo + OS. Rules: on X11, reject single-key combos and report "Add a modifier to capture this key outside Lumotia"; on Windows, reject combos whose only modifier is a right-hand variant (RCtrl/RAlt — per `Handy` #966); on macOS, reject Fn-only combos. Block save button + surface inline "why" copy. | No |
| 4 | **#10**: detect focused-app class; force clipboard-only paste in terminals | Extend `src-tauri/src/commands/paste.rs::paste_text` to look up the focused window class (GetForegroundWindow → class name on Windows; `xdotool getactivewindow getwindowclassname` on Linux X11; `CGWindowListCopyWindowInfo` → ownerName on macOS). On a known-terminal class (`Alacritty`, `kitty`, `gnome-terminal-server`, `WindowsTerminal`, `Code`, `iTerm2`, `Terminal`, etc.) skip the keystroke and just set the clipboard; return `outcome.pasted = false, outcome.copied = true, message = "Terminal detected — clipboard only"`. UX handles that message already. | No |
| 5 | **#11**: versioned settings schema with forward migration | `src/lib/stores/page.svelte.ts` currently reads `magnotia_settings` localStorage blob via `parseStoredJson` and spreads it over `defaults`. Add a `SettingsSchemaVersion` integer (start at 1) and a `migrateSettings(raw, toVersion)` helper. Persist `{ version, data }` on save; read both on load; run migrations in order; fall back cleanly on corruption (drop to defaults, toast the user once). Every new field B adds (below) bumps the version. | No |
| 5 | **#11**: versioned settings schema with forward migration | `src/lib/stores/page.svelte.ts` currently reads `lumotia_settings` localStorage blob via `parseStoredJson` and spreads it over `defaults`. Add a `SettingsSchemaVersion` integer (start at 1) and a `migrateSettings(raw, toVersion)` helper. Persist `{ version, data }` on save; read both on load; run migrations in order; fall back cleanly on corruption (drop to defaults, toast the user once). Every new field B adds (below) bumps the version. | No |
**Commit boundary:** `cargo build -p magnotia && npm run check` green for
**Commit boundary:** `cargo build -p lumotia && npm run check` green for
every commit; JS-side vitest isn't set up in this repo, so the
migration tests live under `src/lib/utils/__tests__/` as pure TS +
`svelte-check`. If tests need a runner we borrow Codex's setup in
@@ -76,7 +76,7 @@ Phase B.2. **Stop for review.**
| Seq | Item | Effect | Depends on A? |
|---|---|---|---|
| 6 | **#14 (UI)**: GPU enumeration + explicit device selector in Settings | Adds a `Compute device` row to `SettingsPage.svelte` under the existing `openSection === 'transcription'` section. Reads `runtimeCapabilities.activeComputeDevice` (A ships this in Phase A.1 #1) and `list_gpus()` (A ships in Phase A.2). If `list_gpus` isn't shipped yet, B ships the UI behind `if (runtimeCapabilities.activeComputeDevice)` and a TODO to call `list_gpus` later. `set_preferred_gpu(id)` is wired to a save-on-select handler with a "Restart to apply" toast. No default change until user picks. | Yes — A ships `list_gpus` in Phase A.2. B stubs behind the `activeComputeDevice` check until then. |
| 7 | **#15**: named LLM prompt presets | Preset data lives client-side in `src/lib/stores/promptPresets.svelte.ts` (new). Five presets shipped: `Quick clean` (default), `Email`, `Meeting notes`, `Code`, `Summary`. Each is `{ id, name, systemPrompt, modelTier }`. User-editable list stored in `localStorage['magnotia_prompt_presets']` with migration hook. Settings gets a new "Prompt presets" sub-card inside `openSection === 'ai'`; DictationPage gets a small preset pill above the Status bar — active preset is applied at cleanup time. Default preset's `systemPrompt` is `CLEANUP_PROMPT` from `llm_client.rs`, so the existing baseline is preserved. | No — uses existing `cleanup_transcript_text_cmd(transcript, profile_id)`. If the backend later needs `system_prompt_override` (not strictly needed for MVP — UI just restricts _when_ cleanup fires), B adds that with A's sign-off. |
| 7 | **#15**: named LLM prompt presets | Preset data lives client-side in `src/lib/stores/promptPresets.svelte.ts` (new). Five presets shipped: `Quick clean` (default), `Email`, `Meeting notes`, `Code`, `Summary`. Each is `{ id, name, systemPrompt, modelTier }`. User-editable list stored in `localStorage['lumotia_prompt_presets']` with migration hook. Settings gets a new "Prompt presets" sub-card inside `openSection === 'ai'`; DictationPage gets a small preset pill above the Status bar — active preset is applied at cleanup time. Default preset's `systemPrompt` is `CLEANUP_PROMPT` from `llm_client.rs`, so the existing baseline is preserved. | No — uses existing `cleanup_transcript_text_cmd(transcript, profile_id)`. If the backend later needs `system_prompt_override` (not strictly needed for MVP — UI just restricts _when_ cleanup fires), B adds that with A's sign-off. |
| 8 | **#17**: raw-transcript revert with ⌘/Ctrl+Z within 5 s | `src/lib/pages/DictationPage.svelte::finaliseTranscription` keeps `rawTranscript` alongside `transcript`. After paste, start a 5-second window where Ctrl/⌘+Z caught globally (via `@tauri-apps/plugin-global-shortcut` ephemerally, or via Tauri IPC from the main window) replaces the last paste: clipboard reset → previous-transcript paste. Preview overlay adds a 5s countdown chip. Untouched clipboard snapshot from #3 is reused. The revert hook lives in `src/routes/preview/+page.svelte` phase machine: new `revertable: true` transient on `phase === "final"`. | No — builds on #3 and the existing paste command. |
| 9 | **#20**: sound cues for start / stop / complete | Small sound-cue module `src/lib/utils/soundCues.ts`: preloads three short WAV/OGG assets (under `static/sounds/`), uses the WebAudio API, caps volume at the user's mute + slider. Settings adds a new `Sound cues` card under `openSection === 'audio'` with a toggle, three preview buttons, a volume slider. Default: **on**, 50% volume. | No |