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>
This commit is contained in:
@@ -182,34 +182,34 @@ Three workflows in `.github/workflows/`:
|
||||
|
||||
## Clean-install test plan
|
||||
|
||||
Run on a spare user account or a fresh VM, with no prior Magnotia /
|
||||
Magnotia data. Three iterations: one per platform.
|
||||
Run on a spare user account or a fresh VM, with no prior Lumotia /
|
||||
Lumotia data. Three iterations: one per platform.
|
||||
|
||||
1. Install the artefact from the platform's `build.yml` output.
|
||||
2. Launch from a clean shell (`magnotia` from PATH, or the .app /
|
||||
2. Launch from a clean shell (`lumotia` from PATH, or the .app /
|
||||
Start-menu shortcut).
|
||||
3. Verify first-run setup flow renders. Walk through the Whisper /
|
||||
LLM model download for the smallest tier.
|
||||
4. Confirm app data lands at the expected path:
|
||||
- Linux: `~/.local/share/magnotia/` (will become `~/.local/share/
|
||||
magnotia/` after Phase 10b rename).
|
||||
- macOS: `~/Library/Application Support/com.corbel.magnotia/`.
|
||||
- Windows: `%APPDATA%\com.corbel.magnotia\`.
|
||||
- Linux: `~/.local/share/lumotia/` (will become `~/.local/share/
|
||||
lumotia/` after Phase 10b rename).
|
||||
- macOS: `~/Library/Application Support/com.corbel.lumotia/`.
|
||||
- Windows: `%APPDATA%\com.corbel.lumotia\`.
|
||||
5. Record a 10-second brain-dump → cleanup → task extraction.
|
||||
Confirm no log leakage to stderr that references `target/` or
|
||||
dev-only paths.
|
||||
6. Quit the app. Open the SQLite db (`magnotia.db` for now) and verify
|
||||
6. Quit the app. Open the SQLite db (`lumotia.db` for now) and verify
|
||||
`SELECT version FROM schema_version ORDER BY version DESC LIMIT
|
||||
1` returns `14`.
|
||||
7. Re-launch. Confirm settings persist, history shows the test
|
||||
transcript with manual + LLM tags.
|
||||
8. Optional but recommended: launch with `RUST_LOG=debug` once and
|
||||
archive the log. Anything referencing `/home/jake/Documents/
|
||||
CORBEL-Projects/magnotia/target/` is a dev-leak bug.
|
||||
CORBEL-Projects/lumotia/target/` is a dev-leak bug.
|
||||
|
||||
For Phase 10c this gets re-run after the rename sweep to confirm
|
||||
the migration shim correctly moves `~/.local/share/magnotia/` →
|
||||
`~/.local/share/magnotia/` and renames `magnotia.db` → `magnotia.db`.
|
||||
the migration shim correctly moves `~/.local/share/lumotia/` →
|
||||
`~/.local/share/lumotia/` and renames `lumotia.db` → `lumotia.db`.
|
||||
|
||||
## Walkthrough checklist (deferred from Phase 9d)
|
||||
|
||||
@@ -255,7 +255,7 @@ def contrast(c1, c2):
|
||||
|
||||
## Anchors
|
||||
|
||||
- Roadmap: [docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md](../../roadmap/2026-04-23-magnotia-feature-complete-roadmap.md)
|
||||
- Roadmap: [docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md](../../roadmap/2026-04-23-lumotia-feature-complete-roadmap.md)
|
||||
- Phase 9 spec: [docs/superpowers/specs/2026-04-24-phase9-polish-debt-design.md](../specs/2026-04-24-phase9-polish-debt-design.md)
|
||||
- Release-blocker index: [docs/issues/README.md](../../issues/README.md)
|
||||
- Latest handover: [HANDOVER.md](../../../HANDOVER.md)
|
||||
|
||||
@@ -14,7 +14,7 @@ author: Hermes Agent with Jake Sames
|
||||
|
||||
- Launched via `./run.sh` from `/home/jake/Documents/CORBEL-Projects/transcription-app`.
|
||||
- Dev server: Vite on `localhost:1420`.
|
||||
- Tauri binary: `/home/jake/Documents/CORBEL-Projects/transcription-app/target/debug/magnotia`.
|
||||
- Tauri binary: `/home/jake/Documents/CORBEL-Projects/transcription-app/target/debug/lumotia`.
|
||||
- Launch visible to Jake after restarting under PTY.
|
||||
|
||||
## Results
|
||||
@@ -29,7 +29,7 @@ author: Hermes Agent with Jake Sames
|
||||
|
||||
## 2026/05/12 — re-validation pass after engine slop residuals + Area A
|
||||
|
||||
Context: residuals B (`184214b`), hotkey tracing finishing (`48c4838`), and Area A storage-error typing (`52565ea` + `a36ae7e`) landed today. Launched magnotia under `RUST_LOG=info,magnotia=debug,magnotia_lib::commands::live=debug` to validate that the new tracing + storage-error semantics held up in a real session.
|
||||
Context: residuals B (`184214b`), hotkey tracing finishing (`48c4838`), and Area A storage-error typing (`52565ea` + `a36ae7e`) landed today. Launched lumotia under `RUST_LOG=info,lumotia=debug,lumotia_lib::commands::live=debug` to validate that the new tracing + storage-error semantics held up in a real session.
|
||||
|
||||
| Check | Result | Notes |
|
||||
|---|---|---|
|
||||
@@ -39,6 +39,6 @@ Context: residuals B (`184214b`), hotkey tracing finishing (`48c4838`), and Area
|
||||
| No obvious WARN/ERROR toast or crash on smoke | PASS | Confirmed by Jake. |
|
||||
| Longer-form dogfood (transcribe + LLM cleanup + tagging) | NOT RUN | Hermes session crashed before the longer pass could start. The LLM tagging crash from the 2026/05/10 entry above remains the outstanding release-blocker. |
|
||||
|
||||
Observability check — tracing pipeline confirmed working under the new default filter (`magnotia=info,magnotia_lib=info,magnotia_audio=info,magnotia_startup=info,magnotia_hotkey=info,magnotia_ai_formatting=info`). Per-chunk speech-gate skip + dispatch events show under `magnotia_lib::commands::live=debug` as intended.
|
||||
Observability check — tracing pipeline confirmed working under the new default filter (`lumotia=info,lumotia_lib=info,lumotia_audio=info,lumotia_startup=info,lumotia_hotkey=info,lumotia_ai_formatting=info`). Per-chunk speech-gate skip + dispatch events show under `lumotia_lib::commands::live=debug` as intended.
|
||||
|
||||
Storage-error semantics: no opportunity to exercise typed storage failures this session (no FK violation, NotFound, or migration replay path was hit). Re-validation deferred to next dogfood pass when a path that produces a real storage error can be triggered deliberately.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
- Branch: `main` (Jake's standing rule — phases ship on main, not feature branches).
|
||||
- Commit after each task. Format: `feat(gamification): [what changed]`, or `fix(gamification): …` for a within-phase correction. Each task's final step is the commit.
|
||||
- Test runner on Rust: `cargo test -p magnotia-storage` (or crate name in workspace). Frontend has **no test runner** — `npm run check` is the only type/lint gate; correctness is verified by cargo tests on the backend and manual dogfood on the frontend, deferred to Phase 10a QC.
|
||||
- Test runner on Rust: `cargo test -p lumotia-storage` (or crate name in workspace). Frontend has **no test runner** — `npm run check` is the only type/lint gate; correctness is verified by cargo tests on the backend and manual dogfood on the frontend, deferred to Phase 10a QC.
|
||||
- British English in user-facing copy.
|
||||
- No em / en dashes in prose or strings.
|
||||
|
||||
@@ -97,7 +97,7 @@ async fn migration_v13_adds_auto_completed_column() {
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `cargo test -p magnotia-storage migration_v13 -- --nocapture`
|
||||
Run: `cargo test -p lumotia-storage migration_v13 -- --nocapture`
|
||||
Expected: FAIL with "no such column: auto_completed" or "expected auto_completed column" depending on which assertion fires first.
|
||||
|
||||
- [ ] **Step 3: Add the migration entry**
|
||||
@@ -130,12 +130,12 @@ In `crates/storage/src/migrations.rs`, append to the `MIGRATIONS: &[(i64, &str,
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `cargo test -p magnotia-storage migration_v13 -- --nocapture`
|
||||
Run: `cargo test -p lumotia-storage migration_v13 -- --nocapture`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Run the full storage test suite to confirm no regression**
|
||||
|
||||
Run: `cargo test -p magnotia-storage`
|
||||
Run: `cargo test -p lumotia-storage`
|
||||
Expected: all existing tests still pass.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
@@ -209,7 +209,7 @@ async fn cascade_sets_auto_completed_on_parent_only() {
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `cargo test -p magnotia-storage cascade_sets_auto_completed -- --nocapture`
|
||||
Run: `cargo test -p lumotia-storage cascade_sets_auto_completed -- --nocapture`
|
||||
Expected: FAIL — parent_auto is 0 because the cascade UPDATE doesn't set the flag yet.
|
||||
|
||||
- [ ] **Step 3: Modify the cascade UPDATE**
|
||||
@@ -246,12 +246,12 @@ if pending == 0 {
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `cargo test -p magnotia-storage cascade_sets_auto_completed -- --nocapture`
|
||||
Run: `cargo test -p lumotia-storage cascade_sets_auto_completed -- --nocapture`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Run the full storage test suite**
|
||||
|
||||
Run: `cargo test -p magnotia-storage`
|
||||
Run: `cargo test -p lumotia-storage`
|
||||
Expected: all tests pass.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
@@ -317,7 +317,7 @@ async fn uncomplete_clears_auto_completed_on_parent() {
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `cargo test -p magnotia-storage uncomplete_clears_auto_completed -- --nocapture`
|
||||
Run: `cargo test -p lumotia-storage uncomplete_clears_auto_completed -- --nocapture`
|
||||
Expected: FAIL on the `parent_auto` assertion (still 1).
|
||||
|
||||
- [ ] **Step 3: Modify both UPDATE statements in `uncomplete_task`**
|
||||
@@ -357,12 +357,12 @@ sqlx::query(
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `cargo test -p magnotia-storage uncomplete_clears_auto_completed -- --nocapture`
|
||||
Run: `cargo test -p lumotia-storage uncomplete_clears_auto_completed -- --nocapture`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Run the full storage test suite**
|
||||
|
||||
Run: `cargo test -p magnotia-storage`
|
||||
Run: `cargo test -p lumotia-storage`
|
||||
Expected: all tests pass.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
@@ -507,7 +507,7 @@ async fn list_recent_completions_uses_local_day_boundary() {
|
||||
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `cargo test -p magnotia-storage list_recent_completions -- --nocapture`
|
||||
Run: `cargo test -p lumotia-storage list_recent_completions -- --nocapture`
|
||||
Expected: FAIL — function not defined.
|
||||
|
||||
- [ ] **Step 3: Add the struct and function**
|
||||
@@ -607,17 +607,17 @@ pub use database::{DailyCompletionCount, list_recent_completions};
|
||||
|
||||
- [ ] **Step 4: Run tests to verify they pass**
|
||||
|
||||
Run: `cargo test -p magnotia-storage list_recent_completions -- --nocapture`
|
||||
Run: `cargo test -p lumotia-storage list_recent_completions -- --nocapture`
|
||||
Expected: all 4 new tests PASS.
|
||||
|
||||
- [ ] **Step 5: Run the full storage test suite**
|
||||
|
||||
Run: `cargo test -p magnotia-storage`
|
||||
Run: `cargo test -p lumotia-storage`
|
||||
Expected: all tests pass.
|
||||
|
||||
- [ ] **Step 6: Verify clippy + fmt**
|
||||
|
||||
Run: `cargo clippy -p magnotia-storage -- -D warnings && cargo fmt --check`
|
||||
Run: `cargo clippy -p lumotia-storage -- -D warnings && cargo fmt --check`
|
||||
Expected: clean.
|
||||
|
||||
- [ ] **Step 7: Commit**
|
||||
@@ -647,7 +647,7 @@ EOF
|
||||
|
||||
- [ ] **Step 1: Add the import at the top of `src-tauri/src/commands/tasks.rs`**
|
||||
|
||||
Update the existing `use magnotia_storage::{...}` block (currently starting at line 10) to include the new symbols. Add `DailyCompletionCount, list_recent_completions as db_list_recent_completions` alongside the existing entries.
|
||||
Update the existing `use lumotia_storage::{...}` block (currently starting at line 10) to include the new symbols. Add `DailyCompletionCount, list_recent_completions as db_list_recent_completions` alongside the existing entries.
|
||||
|
||||
- [ ] **Step 2: Add the command at the end of `src-tauri/src/commands/tasks.rs`**
|
||||
|
||||
@@ -676,12 +676,12 @@ In `src-tauri/src/lib.rs`, inside the `invoke_handler!` block, below the existin
|
||||
|
||||
- [ ] **Step 4: Compile**
|
||||
|
||||
Run: `cargo build -p magnotia`
|
||||
Run: `cargo build -p lumotia`
|
||||
Expected: clean build.
|
||||
|
||||
- [ ] **Step 5: Verify clippy + fmt**
|
||||
|
||||
Run: `cargo clippy -p magnotia -- -D warnings && cargo fmt --check`
|
||||
Run: `cargo clippy -p lumotia -- -D warnings && cargo fmt --check`
|
||||
Expected: clean.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
@@ -691,7 +691,7 @@ git add src-tauri/src/commands/tasks.rs src-tauri/src/lib.rs
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat(gamification): list_recent_completions_cmd Tauri wrapper
|
||||
|
||||
Thin wrapper over magnotia_storage::list_recent_completions, parameterised
|
||||
Thin wrapper over lumotia_storage::list_recent_completions, parameterised
|
||||
by day count. Serialises to camelCase JSON (day, count).
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||||
@@ -769,10 +769,10 @@ EOF
|
||||
//
|
||||
// Refresh triggers:
|
||||
// - module load (first time)
|
||||
// - magnotia:task-completed (from page.svelte.ts completeTask)
|
||||
// - magnotia:step-completed (from MicroSteps.svelte)
|
||||
// - magnotia:task-uncompleted (new event — emitted by uncompleteTask)
|
||||
// - magnotia:task-deleted (new event — emitted by deleteTask)
|
||||
// - lumotia:task-completed (from page.svelte.ts completeTask)
|
||||
// - lumotia:step-completed (from MicroSteps.svelte)
|
||||
// - lumotia:task-uncompleted (new event — emitted by uncompleteTask)
|
||||
// - lumotia:task-deleted (new event — emitted by deleteTask)
|
||||
// - window focus (for day rollover while the app stayed open
|
||||
// past midnight)
|
||||
//
|
||||
@@ -813,10 +813,10 @@ if (typeof window !== "undefined") {
|
||||
const handler = () => {
|
||||
refresh().catch(() => {});
|
||||
};
|
||||
window.addEventListener("magnotia:task-completed", handler);
|
||||
window.addEventListener("magnotia:step-completed", handler);
|
||||
window.addEventListener("magnotia:task-uncompleted", handler);
|
||||
window.addEventListener("magnotia:task-deleted", handler);
|
||||
window.addEventListener("lumotia:task-completed", handler);
|
||||
window.addEventListener("lumotia:step-completed", handler);
|
||||
window.addEventListener("lumotia:task-uncompleted", handler);
|
||||
window.addEventListener("lumotia:task-deleted", handler);
|
||||
window.addEventListener("focus", handler);
|
||||
|
||||
if (hasTauriRuntime()) {
|
||||
@@ -1034,12 +1034,12 @@ EOF
|
||||
|
||||
---
|
||||
|
||||
### Task 10: Dispatch `magnotia:task-uncompleted` + `magnotia:task-deleted`
|
||||
### Task 10: Dispatch `lumotia:task-uncompleted` + `lumotia:task-deleted`
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/lib/stores/page.svelte.ts` — `uncompleteTask` (line 470-479) and `deleteTask` (line 438-451).
|
||||
|
||||
- [ ] **Step 1: Emit `magnotia:task-uncompleted` from `uncompleteTask`**
|
||||
- [ ] **Step 1: Emit `lumotia:task-uncompleted` from `uncompleteTask`**
|
||||
|
||||
Current body:
|
||||
```ts
|
||||
@@ -1060,11 +1060,11 @@ Replace the try-block body with:
|
||||
await invoke("uncomplete_task_cmd", { id });
|
||||
applyLocalTaskUpdate(id, { done: false, doneAt: null });
|
||||
if (typeof window !== "undefined") {
|
||||
window.dispatchEvent(new CustomEvent("magnotia:task-uncompleted", { detail: { id } }));
|
||||
window.dispatchEvent(new CustomEvent("lumotia:task-uncompleted", { detail: { id } }));
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Emit `magnotia:task-deleted` from `deleteTask`**
|
||||
- [ ] **Step 2: Emit `lumotia:task-deleted` from `deleteTask`**
|
||||
|
||||
Current body:
|
||||
```ts
|
||||
@@ -1087,7 +1087,7 @@ Add the dispatch inside the success path, right after `broadcastTasks();`:
|
||||
|
||||
```ts
|
||||
if (typeof window !== "undefined") {
|
||||
window.dispatchEvent(new CustomEvent("magnotia:task-deleted", { detail: { id } }));
|
||||
window.dispatchEvent(new CustomEvent("lumotia:task-deleted", { detail: { id } }));
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1105,7 +1105,7 @@ feat(gamification): emit task-uncompleted + task-deleted events
|
||||
|
||||
Phase 8 completionStats store listens on these events to refresh the
|
||||
daily count. Keeps the badge + sparkline accurate after un-tick / delete
|
||||
paths, which don't currently fire magnotia:task-completed.
|
||||
paths, which don't currently fire lumotia:task-completed.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||||
EOF
|
||||
@@ -1222,7 +1222,7 @@ Record any deviations in the handover. Do not mark this step complete on compile
|
||||
### Task 13: Update roadmap and handover
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md` (Phase 8 section — mark shipped, fold the revised-dropped-grace-days line into past tense).
|
||||
- Modify: `docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md` (Phase 8 section — mark shipped, fold the revised-dropped-grace-days line into past tense).
|
||||
- Modify: `HANDOVER.md` (end-of-session summary).
|
||||
|
||||
- [ ] **Step 1: Update roadmap Phase 8 status**
|
||||
@@ -1247,7 +1247,7 @@ Replace the session summary with today's state:
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md HANDOVER.md
|
||||
git add docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md HANDOVER.md
|
||||
git commit -m "$(cat <<'EOF'
|
||||
docs(phase8): mark Phase 8 shipped + refresh handover
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
**Architecture:** See companion spec for full detail. Four sub-phases: 9a export plumbing, 9b LLM tags, 9c Settings restructure, 9d visual + a11y polish.
|
||||
|
||||
**Tech Stack:** Rust + Tauri 2, `tauri-plugin-dialog` (already installed), `magnotia-llm` (already wired to llama-cpp-2), Svelte 5 runes, TypeScript, Tailwind v4, Lucide icons.
|
||||
**Tech Stack:** Rust + Tauri 2, `tauri-plugin-dialog` (already installed), `lumotia-llm` (already wired to llama-cpp-2), Svelte 5 runes, TypeScript, Tailwind v4, Lucide icons.
|
||||
|
||||
**Spec:** [docs/superpowers/specs/2026-04-24-phase9-polish-debt-design.md](../specs/2026-04-24-phase9-polish-debt-design.md)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
Critical-review pass against the actual codebase (after Codex was unavailable for a cross-model read) surfaced three mismatches between the plan's prescribed code and what the repo actually contains. Implementations adapt as follows.
|
||||
|
||||
**1. `magnotia-llm` API.** Plan referenced `LlamaEngine::generate_chat(messages, config).await`. Actual: `LlmEngine::generate(prompt: &str, config: &GenerationConfig) -> Result<String, EngineError>` — *synchronous*, prompt is a single rendered string, no chat-message vec. The engine struct is `LlmEngine` not `LlamaEngine`. Loaded via `engine.load(model_path)` (sync, &self). The closest in-tree analogue to the new `extract_content_tags` is `LlmEngine::cleanup_text` — same crate, same generate-with-prompt shape; copy that pattern. Tasks 7 + 8 code samples are guides, not literals.
|
||||
**1. `lumotia-llm` API.** Plan referenced `LlamaEngine::generate_chat(messages, config).await`. Actual: `LlmEngine::generate(prompt: &str, config: &GenerationConfig) -> Result<String, EngineError>` — *synchronous*, prompt is a single rendered string, no chat-message vec. The engine struct is `LlmEngine` not `LlamaEngine`. Loaded via `engine.load(model_path)` (sync, &self). The closest in-tree analogue to the new `extract_content_tags` is `LlmEngine::cleanup_text` — same crate, same generate-with-prompt shape; copy that pattern. Tasks 7 + 8 code samples are guides, not literals.
|
||||
|
||||
**2. Tauri `AppState`.** Plan referenced `state.llm.read().await.engine.as_ref()`. Actual: `AppState.llm_engine: Arc<LlmEngine>` — direct, no RwLock, accessed as `state.llm_engine.as_ref()`. Existing LLM commands file is `src-tauri/src/commands/llm.rs` (already there — do not create a new one).
|
||||
|
||||
@@ -43,7 +43,7 @@ Fix in scope (decided 2026-04-24, "do it properly so we don't need to revisit"):
|
||||
**TDD steps:**
|
||||
1. Storage test: migration v14 adds `llm_tags TEXT NOT NULL DEFAULT ''` column; pre-existing rows default to empty string.
|
||||
2. Storage test: `db_update_transcript(.., None, Some("topic:x,intent:y"))` writes only `llm_tags` and leaves `manual_tags` untouched.
|
||||
3. Tauri command compile-check via `cargo build -p magnotia`.
|
||||
3. Tauri command compile-check via `cargo build -p lumotia`.
|
||||
4. Frontend `npm run check` clean.
|
||||
|
||||
Commit message: `feat(phase9): migration v14 + tag persistence wiring`.
|
||||
@@ -72,7 +72,7 @@ Tasks 8.5 inserted between 8 and 9. Subsequent task numbers (11..16) unchanged.
|
||||
- Every Phase 9 addition with motion respects `prefers-reduced-motion`.
|
||||
- Phase 8 gotchas carried forward:
|
||||
- `$derived` cannot export at `.svelte.ts` module scope — use `export function` instead.
|
||||
- `#[derive(sqlx::FromRow)]` is not available in `magnotia-storage` (not expected to fire in this phase; noted for safety).
|
||||
- `#[derive(sqlx::FromRow)]` is not available in `lumotia-storage` (not expected to fire in this phase; noted for safety).
|
||||
|
||||
---
|
||||
|
||||
@@ -97,7 +97,7 @@ Tasks 8.5 inserted between 8 and 9. Subsequent task numbers (11..16) unchanged.
|
||||
- `src/lib/stores/page.svelte.ts` — hydrate / persist `llmTags`.
|
||||
- `src/lib/utils/frontmatter.ts` — include `llmTags` in `buildFrontmatter` tag union.
|
||||
- `src/lib/components/CompletionSparkline.svelte` — friendlier aria-label, per-bar `<title>`, `tabindex`, stagger entrance.
|
||||
- `docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md` — mark Phase 9 shipped.
|
||||
- `docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md` — mark Phase 9 shipped.
|
||||
- `HANDOVER.md` — end-of-session state.
|
||||
|
||||
**Files deleted:** None.
|
||||
@@ -144,7 +144,7 @@ mod tests {
|
||||
async fn write_text_file_errors_on_bad_parent() {
|
||||
// Parent dir does not exist → expect Err.
|
||||
let result = write_text_file_cmd(
|
||||
"/definitely-not-a-real-path-magnotia-phase9/out.md".into(),
|
||||
"/definitely-not-a-real-path-lumotia-phase9/out.md".into(),
|
||||
"x".into(),
|
||||
)
|
||||
.await;
|
||||
@@ -157,7 +157,7 @@ If `tempfile` is not already a workspace dev-dep, add it to `src-tauri/Cargo.tom
|
||||
|
||||
- [ ] **Step 3: Run test to verify it fails**
|
||||
|
||||
Run: `cargo test -p magnotia write_text_file -- --nocapture`
|
||||
Run: `cargo test -p lumotia write_text_file -- --nocapture`
|
||||
Expected: FAIL — `write_text_file_cmd` not defined.
|
||||
|
||||
- [ ] **Step 4: Add the command**
|
||||
@@ -177,7 +177,7 @@ pub async fn write_text_file_cmd(path: String, contents: String) -> Result<(), S
|
||||
|
||||
- [ ] **Step 5: Tests pass**
|
||||
|
||||
Run: `cargo test -p magnotia write_text_file -- --nocapture`
|
||||
Run: `cargo test -p lumotia write_text_file -- --nocapture`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
@@ -218,7 +218,7 @@ Add the line inside the block (alphabetical neighbourhood or end — match local
|
||||
|
||||
- [ ] **Step 3: Compile**
|
||||
|
||||
Run: `cargo build -p magnotia`
|
||||
Run: `cargo build -p lumotia`
|
||||
Expected: clean build.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
@@ -627,7 +627,7 @@ pub use prompts::{ContentTags, INTENT_CLOSED_SET, is_valid_intent};
|
||||
|
||||
- [ ] **Step 4: Type-check**
|
||||
|
||||
Run: `cargo build -p magnotia-llm && cargo clippy -p magnotia-llm -- -D warnings`
|
||||
Run: `cargo build -p lumotia-llm && cargo clippy -p lumotia-llm -- -D warnings`
|
||||
Expected: clean.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
@@ -659,10 +659,10 @@ EOF
|
||||
|
||||
```rust
|
||||
// crates/llm/tests/content_tags_smoke.rs
|
||||
use magnotia_llm::{extract_content_tags, is_valid_intent, model_manager::LlmModelId};
|
||||
use lumotia_llm::{extract_content_tags, is_valid_intent, model_manager::LlmModelId};
|
||||
|
||||
// Marked #[ignore] so it does not run in default cargo test (the model
|
||||
// load is heavy). Run explicitly: cargo test -p magnotia-llm --test
|
||||
// load is heavy). Run explicitly: cargo test -p lumotia-llm --test
|
||||
// content_tags_smoke -- --ignored --nocapture.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
@@ -685,14 +685,14 @@ async fn extract_content_tags_on_short_transcript() {
|
||||
assert!(is_valid_intent(&tags.intent), "intent in closed set: {tags:?}");
|
||||
}
|
||||
|
||||
async fn load_local_tier0_engine() -> Option<magnotia_llm::LlamaEngine> {
|
||||
async fn load_local_tier0_engine() -> Option<lumotia_llm::LlamaEngine> {
|
||||
// Use the existing recommend_tier / model_manager path to find a
|
||||
// locally-downloaded model file. Skip the test if none is present.
|
||||
let tier = magnotia_llm::recommend_tier();
|
||||
let info = magnotia_llm::LlmModelInfo::from_id(&LlmModelId::from_tier(tier))?;
|
||||
let tier = lumotia_llm::recommend_tier();
|
||||
let info = lumotia_llm::LlmModelInfo::from_id(&LlmModelId::from_tier(tier))?;
|
||||
let path = info.local_path().ok()?;
|
||||
if !path.exists() { return None; }
|
||||
magnotia_llm::LlamaEngine::load(&path).await.ok()
|
||||
lumotia_llm::LlamaEngine::load(&path).await.ok()
|
||||
}
|
||||
```
|
||||
|
||||
@@ -757,9 +757,9 @@ pub async fn extract_content_tags(
|
||||
- [ ] **Step 3: Build + tests**
|
||||
|
||||
```
|
||||
cargo build -p magnotia-llm
|
||||
cargo test -p magnotia-llm # excludes #[ignore] — should still be green
|
||||
cargo clippy -p magnotia-llm -- -D warnings
|
||||
cargo build -p lumotia-llm
|
||||
cargo test -p lumotia-llm # excludes #[ignore] — should still be green
|
||||
cargo clippy -p lumotia-llm -- -D warnings
|
||||
cargo fmt --check
|
||||
```
|
||||
|
||||
@@ -787,13 +787,13 @@ EOF
|
||||
### Task 8: `extract_content_tags_cmd` Tauri wrapper
|
||||
|
||||
**Files:**
|
||||
- Modify: the existing LLM-commands file under `src-tauri/src/commands/` (grep for `magnotia_llm::` to find it; typically something like `llm.rs` or `ai.rs`). If absent, create `src-tauri/src/commands/llm.rs` and register the module in `commands/mod.rs`.
|
||||
- Modify: the existing LLM-commands file under `src-tauri/src/commands/` (grep for `lumotia_llm::` to find it; typically something like `llm.rs` or `ai.rs`). If absent, create `src-tauri/src/commands/llm.rs` and register the module in `commands/mod.rs`.
|
||||
- Modify: `src-tauri/src/lib.rs` — register the command.
|
||||
|
||||
- [ ] **Step 1: Add the command**
|
||||
|
||||
```rust
|
||||
use magnotia_llm::{extract_content_tags as llm_extract_content_tags, ContentTags};
|
||||
use lumotia_llm::{extract_content_tags as llm_extract_content_tags, ContentTags};
|
||||
// …alongside existing LLM imports.
|
||||
|
||||
#[tauri::command]
|
||||
@@ -827,7 +827,7 @@ In `src-tauri/src/lib.rs` `invoke_handler!`:
|
||||
|
||||
- [ ] **Step 3: Build**
|
||||
|
||||
Run: `cargo build -p magnotia && cargo clippy -p magnotia -- -D warnings && cargo fmt --check`
|
||||
Run: `cargo build -p lumotia && cargo clippy -p lumotia -- -D warnings && cargo fmt --check`
|
||||
Expected: clean.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
@@ -837,7 +837,7 @@ git add src-tauri/src/commands/ src-tauri/src/lib.rs
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat(phase9): extract_content_tags_cmd Tauri wrapper
|
||||
|
||||
Bridges magnotia_llm::extract_content_tags to the frontend. Returns a
|
||||
Bridges lumotia_llm::extract_content_tags to the frontend. Returns a
|
||||
ContentTags object serialised to the {topic, intent} shape the
|
||||
frontend stores on item.llmTags.
|
||||
|
||||
@@ -1560,7 +1560,7 @@ EOF
|
||||
### Task 16: Full verification pass + roadmap + HANDOVER
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md` — mark Phase 9 shipped.
|
||||
- Modify: `docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md` — mark Phase 9 shipped.
|
||||
- Modify: `HANDOVER.md` — end-of-session state.
|
||||
|
||||
- [ ] **Step 1: Full Rust gate**
|
||||
@@ -1605,7 +1605,7 @@ Replace the session summary with today's state:
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md HANDOVER.md
|
||||
git add docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md HANDOVER.md
|
||||
git commit -m "$(cat <<'EOF'
|
||||
docs(phase9): mark Phase 9 shipped + refresh HANDOVER
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
**Goal:** Add power-aware and GPU-offload-aware clamps to `inference_thread_count` so Lumenote drops to ~half threads on battery and to a workload-specific floor when fully GPU-offloaded.
|
||||
|
||||
**Architecture:** Two new modules in `magnotia-core`: `power.rs` (Linux sysfs probe with TTL cache) and `tuning.rs` (Workload enum + helper). Both whisper and LLM call sites compute a `gpu_offloaded` bool and pass it in. `vulkan_loader_available()` moves from `src-tauri` to `magnotia-core::hardware` so transcription can call it. Old `constants::inference_thread_count` is removed once both call sites migrate.
|
||||
**Architecture:** Two new modules in `lumotia-core`: `power.rs` (Linux sysfs probe with TTL cache) and `tuning.rs` (Workload enum + helper). Both whisper and LLM call sites compute a `gpu_offloaded` bool and pass it in. `vulkan_loader_available()` moves from `src-tauri` to `lumotia-core::hardware` so transcription can call it. Old `constants::inference_thread_count` is removed once both call sites migrate.
|
||||
|
||||
**Tech Stack:** Rust 2021, `magnotia-core` (existing pure-Rust crate), `num_cpus`, `libloading`, `tracing`, `tempfile` (dev). No Tauri or platform FFI for the core probe — Linux sysfs only in v1.
|
||||
**Tech Stack:** Rust 2021, `lumotia-core` (existing pure-Rust crate), `num_cpus`, `libloading`, `tracing`, `tempfile` (dev). No Tauri or platform FFI for the core probe — Linux sysfs only in v1.
|
||||
|
||||
**Spec:** [docs/superpowers/specs/2026-05-09-battery-gpu-aware-thread-tuning-design.md](../specs/2026-05-09-battery-gpu-aware-thread-tuning-design.md)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
- `crates/core/src/lib.rs` — register new modules, re-export public API.
|
||||
- `crates/core/src/hardware.rs` — add `vulkan_loader_available()`, ported from src-tauri.
|
||||
- `crates/core/src/constants.rs` — remove `inference_thread_count` and the related min/max constants (move semantically to `tuning.rs`; the audio/RAM/VAD/etc. constants stay).
|
||||
- `src-tauri/src/commands/models.rs` — delete local `vulkan_loader_available` definition, replace with `magnotia_core::hardware::vulkan_loader_available` call.
|
||||
- `src-tauri/src/commands/models.rs` — delete local `vulkan_loader_available` definition, replace with `lumotia_core::hardware::vulkan_loader_available` call.
|
||||
- `src-tauri/Cargo.toml` — keep `libloading` since src-tauri still depends on it elsewhere; verify with `cargo tree`.
|
||||
- `crates/transcription/src/whisper_rs_backend.rs` — compute `gpu_offloaded`, call `tuning::inference_thread_count(Workload::Whisper, gpu_offloaded)`.
|
||||
- `crates/llm/src/lib.rs` — compute `gpu_offloaded` after model load, call `tuning::inference_thread_count(Workload::Llm, gpu_offloaded)`.
|
||||
@@ -91,13 +91,13 @@ pub mod power;
|
||||
|
||||
- [ ] **Step 3: Run the test**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib power::tests::power_state_variants_are_distinct`
|
||||
Run: `cargo test -p lumotia-core --lib power::tests::power_state_variants_are_distinct`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
cd /home/jake/Documents/CORBEL-Projects/magnotia
|
||||
cd /home/jake/Documents/CORBEL-Projects/lumotia
|
||||
git add crates/core/Cargo.toml crates/core/src/power.rs crates/core/src/lib.rs
|
||||
git commit -m "feat(core): add PowerState skeleton in new power module"
|
||||
```
|
||||
@@ -183,7 +183,7 @@ mod tests {
|
||||
|
||||
- [ ] **Step 2: Run tests, expect compile failure**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib power::tests`
|
||||
Run: `cargo test -p lumotia-core --lib power::tests`
|
||||
Expected: compile error — `parse_power_state_from_dir` not found.
|
||||
|
||||
- [ ] **Step 3: Implement parser**
|
||||
@@ -244,7 +244,7 @@ fn read_trimmed(path: &Path) -> Option<String> {
|
||||
|
||||
- [ ] **Step 4: Run tests, expect pass**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib power::tests`
|
||||
Run: `cargo test -p lumotia-core --lib power::tests`
|
||||
Expected: all 6 tests pass.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
@@ -317,7 +317,7 @@ Append inside `mod tests` in `crates/core/src/power.rs`:
|
||||
|
||||
- [ ] **Step 2: Run tests, expect compile failure**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib power::tests`
|
||||
Run: `cargo test -p lumotia-core --lib power::tests`
|
||||
Expected: compile error — `probe_power_state`, `with_override` not found.
|
||||
|
||||
- [ ] **Step 3: Implement probe + overrides**
|
||||
@@ -397,7 +397,7 @@ pub(crate) fn with_override<R>(state: Option<PowerState>, body: impl FnOnce() ->
|
||||
|
||||
- [ ] **Step 4: Run tests, expect pass**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib power::tests`
|
||||
Run: `cargo test -p lumotia-core --lib power::tests`
|
||||
Expected: all tests in the module pass (sysfs parser tests from Task 1.2 plus the 5 new override tests).
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
@@ -512,7 +512,7 @@ Append inside `mod tests` in `crates/core/src/power.rs`:
|
||||
|
||||
- [ ] **Step 4: Run tests, expect pass**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib power::tests`
|
||||
Run: `cargo test -p lumotia-core --lib power::tests`
|
||||
Expected: all power tests pass (sysfs parser + override + cache).
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
@@ -648,7 +648,7 @@ pub mod tuning;
|
||||
|
||||
- [ ] **Step 3: Run the test**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib tuning::tests`
|
||||
Run: `cargo test -p lumotia-core --lib tuning::tests`
|
||||
Expected: 3 tests pass.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
@@ -700,7 +700,7 @@ But wait — these test helpers are gated `#[cfg(test)]` so they're only availab
|
||||
|
||||
- [ ] **Step 2: Run, expect failure**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib tuning::tests::battery_halves_thread_count`
|
||||
Run: `cargo test -p lumotia-core --lib tuning::tests::battery_halves_thread_count`
|
||||
Expected: FAIL — assertion that on_battery <= on_ac fails because helper currently ignores power state. (On a 1c host, on_ac and on_battery would both be 2 and the test would no-op via the early `if on_ac > MIN_INFERENCE_THREADS` check; in that environment the test isn't useful. CI hosts with >2 physical cores will exercise it.)
|
||||
|
||||
- [ ] **Step 3: Implement battery clamp**
|
||||
@@ -736,7 +736,7 @@ pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize
|
||||
|
||||
- [ ] **Step 4: Run, expect pass**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib tuning::tests`
|
||||
Run: `cargo test -p lumotia-core --lib tuning::tests`
|
||||
Expected: 4 tests pass.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
@@ -802,7 +802,7 @@ Add to `mod tests` in `crates/core/src/tuning.rs`:
|
||||
|
||||
- [ ] **Step 2: Run, expect failure**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib tuning::tests`
|
||||
Run: `cargo test -p lumotia-core --lib tuning::tests`
|
||||
Expected: GPU-offload tests fail because the helper still ignores `gpu_offloaded`.
|
||||
|
||||
- [ ] **Step 3: Implement GPU-offload clamp**
|
||||
@@ -842,7 +842,7 @@ pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize
|
||||
|
||||
- [ ] **Step 4: Run, expect pass**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib tuning::tests`
|
||||
Run: `cargo test -p lumotia-core --lib tuning::tests`
|
||||
Expected: 8 tests pass.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
@@ -879,7 +879,7 @@ Add to `mod tests` in `crates/core/src/tuning.rs`:
|
||||
|
||||
- [ ] **Step 2: Run, expect pass (already passes, the test is a smoke)**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib tuning::tests::logging_does_not_panic`
|
||||
Run: `cargo test -p lumotia-core --lib tuning::tests::logging_does_not_panic`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 3: Implement per-process log cache**
|
||||
@@ -941,7 +941,7 @@ pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize
|
||||
if let Ok(mut seen) = log_seen().lock() {
|
||||
if seen.insert(key) {
|
||||
tracing::info!(
|
||||
target: "magnotia_core::tuning",
|
||||
target: "lumotia_core::tuning",
|
||||
threads = final_value,
|
||||
workload = ?workload,
|
||||
gpu_offloaded,
|
||||
@@ -968,7 +968,7 @@ pub enum Workload {
|
||||
|
||||
- [ ] **Step 4: Run all tests**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib`
|
||||
Run: `cargo test -p lumotia-core --lib`
|
||||
Expected: all power + tuning tests pass.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
@@ -982,7 +982,7 @@ git commit -m "feat(core): per-process INFO log on first thread-count call per t
|
||||
|
||||
## Phase 3 — Move `vulkan_loader_available` to core
|
||||
|
||||
### Task 3.1: Port function to `magnotia-core::hardware`
|
||||
### Task 3.1: Port function to `lumotia-core::hardware`
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/core/Cargo.toml` (add `libloading = "0.8"`)
|
||||
@@ -1011,7 +1011,7 @@ Add to `crates/core/src/hardware.rs` inside the existing `#[cfg(test)] mod tests
|
||||
|
||||
- [ ] **Step 3: Run, expect compile failure**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib hardware::tests::vulkan_loader_available_does_not_panic`
|
||||
Run: `cargo test -p lumotia-core --lib hardware::tests::vulkan_loader_available_does_not_panic`
|
||||
Expected: compile error — function not defined.
|
||||
|
||||
- [ ] **Step 4: Add `vulkan_loader_available` to hardware.rs**
|
||||
@@ -1056,7 +1056,7 @@ pub fn vulkan_loader_available() -> bool {
|
||||
|
||||
- [ ] **Step 5: Run, expect pass**
|
||||
|
||||
Run: `cargo test -p magnotia-core --lib hardware::tests::vulkan_loader_available_does_not_panic`
|
||||
Run: `cargo test -p lumotia-core --lib hardware::tests::vulkan_loader_available_does_not_panic`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
@@ -1075,10 +1075,10 @@ git commit -m "feat(core): port vulkan_loader_available from src-tauri"
|
||||
|
||||
- [ ] **Step 1: Replace local definition with re-export**
|
||||
|
||||
Find the local `fn vulkan_loader_available()` in `src-tauri/src/commands/models.rs` (lines around 322–350 of the file as of the spec date). Delete the function entirely. Add at the top of the file (or near other `magnotia_core` imports):
|
||||
Find the local `fn vulkan_loader_available()` in `src-tauri/src/commands/models.rs` (lines around 322–350 of the file as of the spec date). Delete the function entirely. Add at the top of the file (or near other `lumotia_core` imports):
|
||||
|
||||
```rust
|
||||
use magnotia_core::hardware::vulkan_loader_available;
|
||||
use lumotia_core::hardware::vulkan_loader_available;
|
||||
```
|
||||
|
||||
The two existing call sites in `models.rs` (around lines 401 and 419) will now resolve to the imported function. Verify with grep that no other callers exist inside src-tauri:
|
||||
@@ -1091,19 +1091,19 @@ Expected output: only the `use` line and the two existing call sites.
|
||||
|
||||
- [ ] **Step 2: Build and run src-tauri's tests**
|
||||
|
||||
Run: `cargo test -p magnotia` (the src-tauri crate name as listed in `src-tauri/Cargo.toml`; verify if unsure with `grep '^name' src-tauri/Cargo.toml`).
|
||||
Run: `cargo test -p lumotia` (the src-tauri crate name as listed in `src-tauri/Cargo.toml`; verify if unsure with `grep '^name' src-tauri/Cargo.toml`).
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 3: Run the existing accelerator-list smoke**
|
||||
|
||||
Run: `cargo test -p magnotia compose_accelerators`
|
||||
Run: `cargo test -p lumotia compose_accelerators`
|
||||
Expected: PASS — confirms the move didn't change behaviour.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add src-tauri/src/commands/models.rs
|
||||
git commit -m "refactor(tauri): use magnotia_core::hardware::vulkan_loader_available"
|
||||
git commit -m "refactor(tauri): use lumotia_core::hardware::vulkan_loader_available"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -1126,14 +1126,14 @@ params.set_n_threads(inference_thread_count() as i32);
|
||||
…and the import at the top:
|
||||
|
||||
```rust
|
||||
use magnotia_core::constants::inference_thread_count;
|
||||
use lumotia_core::constants::inference_thread_count;
|
||||
```
|
||||
|
||||
Replace the import:
|
||||
|
||||
```rust
|
||||
use magnotia_core::tuning::{inference_thread_count, Workload};
|
||||
use magnotia_core::hardware::vulkan_loader_available;
|
||||
use lumotia_core::tuning::{inference_thread_count, Workload};
|
||||
use lumotia_core::hardware::vulkan_loader_available;
|
||||
```
|
||||
|
||||
Replace the call site:
|
||||
@@ -1145,7 +1145,7 @@ params.set_n_threads(inference_thread_count(Workload::Whisper, gpu_offloaded) as
|
||||
|
||||
- [ ] **Step 2: Build and run the existing whisper smoke**
|
||||
|
||||
Run: `cargo test -p magnotia-transcription whisper_rs_smoke`
|
||||
Run: `cargo test -p lumotia-transcription whisper_rs_smoke`
|
||||
Expected: PASS — the helper returns a sensible value (likely 4 or 6 depending on host).
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
@@ -1173,7 +1173,7 @@ let gpu_layers = if use_gpu { u32::MAX } else { 0 };
|
||||
let params = LlamaModelParams::default().with_n_gpu_layers(gpu_layers);
|
||||
// ... LlamaModel::load_from_file_with_params(...) returns `model` ...
|
||||
|
||||
let thread_count = i32::try_from(magnotia_core::constants::inference_thread_count())
|
||||
let thread_count = i32::try_from(lumotia_core::constants::inference_thread_count())
|
||||
.unwrap_or(4);
|
||||
let ctx_params = LlamaContextParams::default()
|
||||
.with_n_ctx(Some(NonZeroU32::new(n_ctx).expect("n_ctx must be non-zero")))
|
||||
@@ -1185,10 +1185,10 @@ The model has been loaded by this point (the `model` binding above this block re
|
||||
|
||||
- [ ] **Step 2: Replace the import + computation**
|
||||
|
||||
Replace the existing `use magnotia_core::constants::inference_thread_count;` (or wherever `constants::inference_thread_count` is referenced) with:
|
||||
Replace the existing `use lumotia_core::constants::inference_thread_count;` (or wherever `constants::inference_thread_count` is referenced) with:
|
||||
|
||||
```rust
|
||||
use magnotia_core::tuning::{inference_thread_count, Workload};
|
||||
use lumotia_core::tuning::{inference_thread_count, Workload};
|
||||
```
|
||||
|
||||
Replace the thread-count computation block. The new shape uses the `gpu_layers` value already computed above and cross-checks against the loaded model's layer count:
|
||||
@@ -1203,7 +1203,7 @@ The cross-check is trivially true today (`gpu_layers = u32::MAX` when `use_gpu`)
|
||||
|
||||
- [ ] **Step 3: Build and run LLM smoke**
|
||||
|
||||
Run: `cargo test -p magnotia-llm`
|
||||
Run: `cargo test -p lumotia-llm`
|
||||
Expected: PASS (smoke tests in `crates/llm/tests/` exercise the load path; if any fail unrelated to this change, investigate before moving on).
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
@@ -1227,7 +1227,7 @@ git commit -m "feat(llm): LLM threads use Workload::Llm + GPU offload detection"
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd /home/jake/Documents/CORBEL-Projects/magnotia
|
||||
cd /home/jake/Documents/CORBEL-Projects/lumotia
|
||||
grep -rn "constants::inference_thread_count\|MIN_INFERENCE_THREADS\|MAX_INFERENCE_THREADS" \
|
||||
--include='*.rs' \
|
||||
crates/ src-tauri/
|
||||
@@ -1255,7 +1255,7 @@ Expected: clean build, no warnings about unused items.
|
||||
- [ ] **Step 4: Run the full test suite**
|
||||
|
||||
Run: `cargo test --workspace`
|
||||
Expected: PASS for `magnotia-core`, `magnotia-llm`, `magnotia-transcription`, `magnotia` (src-tauri). Other crate tests should be unaffected.
|
||||
Expected: PASS for `lumotia-core`, `lumotia-llm`, `lumotia-transcription`, `lumotia` (src-tauri). Other crate tests should be unaffected.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
@@ -1330,8 +1330,8 @@ For the GPU panels: the fixture sweep doesn't reload the whisper context with th
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd /home/jake/Documents/CORBEL-Projects/magnotia
|
||||
MAGNOTIA_THREAD_SWEEP=1 cargo test -p magnotia-transcription --release thread_count_scaling -- --nocapture
|
||||
cd /home/jake/Documents/CORBEL-Projects/lumotia
|
||||
MAGNOTIA_THREAD_SWEEP=1 cargo test -p lumotia-transcription --release thread_count_scaling -- --nocapture
|
||||
```
|
||||
|
||||
Expected: 4 RTF panels print. Note the per-panel sweet spots — they inform whether the constants in `tuning.rs` need adjusting.
|
||||
@@ -1356,8 +1356,8 @@ This is a manual step; no commit unless the smoke uncovers a defect that needs f
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd /home/jake/Documents/CORBEL-Projects/magnotia
|
||||
cargo build --release -p magnotia-transcription -p magnotia-llm
|
||||
cd /home/jake/Documents/CORBEL-Projects/lumotia
|
||||
cargo build --release -p lumotia-transcription -p lumotia-llm
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Unplug the laptop, run a transcription session**
|
||||
@@ -1365,7 +1365,7 @@ cargo build --release -p magnotia-transcription -p magnotia-llm
|
||||
Open Lumenote, dictate a short clip, watch the log output (Tauri devtools or stdout if running via `cargo tauri dev`). Expect a line of the shape:
|
||||
|
||||
```
|
||||
INFO magnotia_core::tuning: inference_thread_count threads=3 workload=Whisper gpu_offloaded=false on_battery=true clamps=["battery"]
|
||||
INFO lumotia_core::tuning: inference_thread_count threads=3 workload=Whisper gpu_offloaded=false on_battery=true clamps=["battery"]
|
||||
```
|
||||
|
||||
(Numbers vary by host. On a 6c12t Ryzen 4650U the expected `threads` is 3.)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name: Area A — storage error inventory and proposed taxonomy
|
||||
type: survey
|
||||
tags: [engine, residuals, area-a, storage, errors, survey]
|
||||
description: Pre-migration survey for engine-slop residuals Area A. Catalogues every MagnotiaError::StorageError construction site in the storage crate, groups by failure mode, proposes a typed magnotia_storage::Error enum with a serializable MagnotiaError::Storage variant on top, and flags ambiguities + migration risks. No code changes yet.
|
||||
description: Pre-migration survey for engine-slop residuals Area A. Catalogues every MagnotiaError::StorageError construction site in the storage crate, groups by failure mode, proposes a typed lumotia_storage::Error enum with a serializable MagnotiaError::Storage variant on top, and flags ambiguities + migration risks. No code changes yet.
|
||||
status: draft
|
||||
---
|
||||
|
||||
@@ -12,7 +12,7 @@ There is no `StorageError` enum to extend. The storage crate has zero local erro
|
||||
|
||||
The Tauri command layer stringifies every error before crossing into the frontend (`Result<T, String>` everywhere via `.map_err(|e| e.to_string())?`), so `MagnotiaError`'s `Serialize` impl is presently unused at the FE/BE boundary. Area E is where that ossifies; Area A's job is to give **backend** code something to branch on — not to fix the frontend.
|
||||
|
||||
Proposed: introduce a new `magnotia_storage::Error` enum in the storage crate, replace the `String` tail of `MagnotiaError::StorageError(String)` with a structured `MagnotiaError::Storage { kind, operation, detail }` variant, and wire the conversion through a `From<storage::Error> for MagnotiaError` impl that flattens the structured error into a serde-friendly shape. Backend code can pattern-match on `storage::Error`; the frontend keeps receiving (slightly nicer) strings until Area E.
|
||||
Proposed: introduce a new `lumotia_storage::Error` enum in the storage crate, replace the `String` tail of `MagnotiaError::StorageError(String)` with a structured `MagnotiaError::Storage { kind, operation, detail }` variant, and wire the conversion through a `From<storage::Error> for MagnotiaError` impl that flattens the structured error into a serde-friendly shape. Backend code can pattern-match on `storage::Error`; the frontend keeps receiving (slightly nicer) strings until Area E.
|
||||
|
||||
## Inventory
|
||||
|
||||
@@ -28,7 +28,7 @@ Proposed: introduce a new `magnotia_storage::Error` enum in the storage crate, r
|
||||
|
||||
### Storage crate context
|
||||
|
||||
- Uses `magnotia_core::error::{MagnotiaError, Result}` directly — no local error type.
|
||||
- Uses `lumotia_core::error::{MagnotiaError, Result}` directly — no local error type.
|
||||
- No `From<sqlx::Error>` impl exists, which is why every sqlx call has an explicit `.map_err(...)`.
|
||||
- `From<std::io::Error> for MagnotiaError` does exist (in `crates/core/src/error.rs`), so directory-creation paths use `?` cleanly.
|
||||
|
||||
@@ -114,7 +114,7 @@ This is **not a sqlx failure**. It's an integrity check we perform manually befo
|
||||
|
||||
### Where it lives
|
||||
|
||||
**Option A (recommended): new `magnotia_storage::Error` enum in the storage crate.**
|
||||
**Option A (recommended): new `lumotia_storage::Error` enum in the storage crate.**
|
||||
|
||||
```rust
|
||||
// crates/storage/src/error.rs
|
||||
@@ -189,7 +189,7 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||
**Why option A:**
|
||||
|
||||
- The taxonomy lives where the failures originate. Storage owns its own error vocabulary.
|
||||
- The storage crate can be tested in isolation without `magnotia_core` understanding its internals.
|
||||
- The storage crate can be tested in isolation without `lumotia_core` understanding its internals.
|
||||
- `From<storage::Error> for MagnotiaError` keeps propagation automatic via `?`.
|
||||
- Sets up Area E to selectively expose storage-error kinds to the frontend without a second migration of call sites.
|
||||
|
||||
@@ -211,7 +211,7 @@ pub enum MagnotiaError {
|
||||
```
|
||||
|
||||
- Less ceremony, one file changes.
|
||||
- But couples the storage taxonomy into `magnotia_core`, which is a leaky abstraction.
|
||||
- But couples the storage taxonomy into `lumotia_core`, which is a leaky abstraction.
|
||||
- Harder to extend later when, say, we add a vocabulary crate (per D1 in the architecture spec) that also wants typed errors — every crate ends up dumping its enum into `MagnotiaError`.
|
||||
|
||||
### How it crosses the MagnotiaError boundary
|
||||
@@ -244,14 +244,14 @@ pub enum StorageKind {
|
||||
InvalidReference,
|
||||
}
|
||||
|
||||
impl From<magnotia_storage::Error> for MagnotiaError {
|
||||
fn from(e: magnotia_storage::Error) -> Self {
|
||||
impl From<lumotia_storage::Error> for MagnotiaError {
|
||||
fn from(e: lumotia_storage::Error) -> Self {
|
||||
let kind = match &e {
|
||||
magnotia_storage::Error::DatabaseOpen { .. } => StorageKind::DatabaseOpen,
|
||||
magnotia_storage::Error::Migration { .. } => StorageKind::Migration,
|
||||
magnotia_storage::Error::Query { .. } => StorageKind::Query,
|
||||
magnotia_storage::Error::NotFound { .. } => StorageKind::NotFound,
|
||||
magnotia_storage::Error::InvalidReference { .. } => StorageKind::InvalidReference,
|
||||
lumotia_storage::Error::DatabaseOpen { .. } => StorageKind::DatabaseOpen,
|
||||
lumotia_storage::Error::Migration { .. } => StorageKind::Migration,
|
||||
lumotia_storage::Error::Query { .. } => StorageKind::Query,
|
||||
lumotia_storage::Error::NotFound { .. } => StorageKind::NotFound,
|
||||
lumotia_storage::Error::InvalidReference { .. } => StorageKind::InvalidReference,
|
||||
};
|
||||
let operation = e.operation_label().into_owned();
|
||||
let detail = e.to_string();
|
||||
@@ -260,17 +260,17 @@ impl From<magnotia_storage::Error> for MagnotiaError {
|
||||
}
|
||||
```
|
||||
|
||||
`operation_label()` is a helper on `storage::Error` returning a `Cow<'static, str>` from the inner enum data. Backend code that wants programmatic recovery downcasts (or rather, the storage call signatures return `Result<_, magnotia_storage::Error>` directly — only public Tauri-facing wrappers eat the `From` conversion).
|
||||
`operation_label()` is a helper on `storage::Error` returning a `Cow<'static, str>` from the inner enum data. Backend code that wants programmatic recovery downcasts (or rather, the storage call signatures return `Result<_, lumotia_storage::Error>` directly — only public Tauri-facing wrappers eat the `From` conversion).
|
||||
|
||||
### Function-signature decision
|
||||
|
||||
The storage crate has 70+ public functions returning `magnotia_core::Result<...>`. Two options:
|
||||
The storage crate has 70+ public functions returning `lumotia_core::Result<...>`. Two options:
|
||||
|
||||
1. **Change all to `magnotia_storage::Result<...>`** and let `?` in callers do the From conversion. Pros: backend code that wants typed errors gets them. Cons: ~70 signatures to touch, and any backend code that wanted the structured error has to import `magnotia_storage::Error`.
|
||||
1. **Change all to `lumotia_storage::Result<...>`** and let `?` in callers do the From conversion. Pros: backend code that wants typed errors gets them. Cons: ~70 signatures to touch, and any backend code that wanted the structured error has to import `lumotia_storage::Error`.
|
||||
|
||||
2. **Keep public signatures as `magnotia_core::Result<...>`, do the conversion at the storage-crate boundary** via an internal `Result<T> = std::result::Result<T, magnotia_storage::Error>` for internal helpers. Public functions then end with `? `(or `.map_err(Into::into))`. Pros: caller signatures unchanged. Cons: callers wanting to pattern-match on storage failure type have nothing to match against (back to square one).
|
||||
2. **Keep public signatures as `lumotia_core::Result<...>`, do the conversion at the storage-crate boundary** via an internal `Result<T> = std::result::Result<T, lumotia_storage::Error>` for internal helpers. Public functions then end with `? `(or `.map_err(Into::into))`. Pros: caller signatures unchanged. Cons: callers wanting to pattern-match on storage failure type have nothing to match against (back to square one).
|
||||
|
||||
**Recommended: option 1.** It's the more honest signature. ~70 public functions get changed, but it's mechanical: `Result<T>` → `magnotia_storage::Result<T>` and the body's `MagnotiaError::StorageError(format!(...))` is what we're replacing anyway. Callers (Tauri commands) that currently `.map_err(|e| e.to_string())?` keep working because the storage error From-converts into MagnotiaError, which is what Display'd into the string they're already producing.
|
||||
**Recommended: option 1.** It's the more honest signature. ~70 public functions get changed, but it's mechanical: `Result<T>` → `lumotia_storage::Result<T>` and the body's `MagnotiaError::StorageError(format!(...))` is what we're replacing anyway. Callers (Tauri commands) that currently `.map_err(|e| e.to_string())?` keep working because the storage error From-converts into MagnotiaError, which is what Display'd into the string they're already producing.
|
||||
|
||||
This also means **Area E later only has to delete `.map_err(|e| e.to_string())?` and change return types** to receive structured errors — no second pass over the storage call sites.
|
||||
|
||||
@@ -333,7 +333,7 @@ The 64 sites in Bucket 3. Operation labels match the current message stem in sna
|
||||
- Derive Serialize and `#[serde(skip)]` the `sqlx::Error` source. Loses source detail in serialised form.
|
||||
- Custom Serialize impl that stringifies the source.
|
||||
- Don't derive Serialize — flatten only at the `MagnotiaError` boundary as proposed above.
|
||||
**Recommendation:** the third. Keeps the storage crate's API surface backend-only; serialisation concerns live in `magnotia_core`. Already reflected in the proposal.
|
||||
**Recommendation:** the third. Keeps the storage crate's API surface backend-only; serialisation concerns live in `lumotia_core`. Already reflected in the proposal.
|
||||
|
||||
6. **Public re-exports from storage crate.** Need to decide: do we re-export `Error`, `Result`, `OpenOp`, `MigrationStep`, `Entity`, `StorageKind` (or its storage-side equivalent) from `crates/storage/src/lib.rs`? Yes — backend code (Tauri commands, future test code) will want to pattern-match. Suggest a `pub mod error;` + `pub use error::{Error, Result, OpenOp, MigrationStep, Entity};` block.
|
||||
|
||||
@@ -347,7 +347,7 @@ The 64 sites in Bucket 3. Operation labels match the current message stem in sna
|
||||
|
||||
### Compile-time gotchas
|
||||
|
||||
- **`?` operator semantics depend on which `Result` is in scope.** If function signature returns `magnotia_core::Result<T>` and body uses `magnotia_storage::Result<T>` internally, every helper boundary needs an explicit `Into::into` or a `?` cascade with `From` plumbed. Doable but easy to miss — recommend going function-by-function, not file-by-file.
|
||||
- **`?` operator semantics depend on which `Result` is in scope.** If function signature returns `lumotia_core::Result<T>` and body uses `lumotia_storage::Result<T>` internally, every helper boundary needs an explicit `Into::into` or a `?` cascade with `From` plumbed. Doable but easy to miss — recommend going function-by-function, not file-by-file.
|
||||
|
||||
- **Test ergonomics.** Storage crate tests at `crates/storage/src/migrations.rs:1027+` currently match on `MagnotiaError::StorageError` patterns. They'll need updating to match on `storage::Error::Migration { step: MigrationStep::Apply, .. }` style. Roughly 5–10 test assertions, all bounded to that file.
|
||||
|
||||
@@ -356,7 +356,7 @@ The 64 sites in Bucket 3. Operation labels match the current message stem in sna
|
||||
- **Do not retitle error messages.** Goal is to preserve the current Display output verbatim where possible, with the operation label carrying the same information as the current message stem. Wording changes belong in a separate pass.
|
||||
|
||||
- **Do not change `MagnotiaError::StorageError(String)` → `MagnotiaError::Storage { ... }` in one PR alongside the storage-crate work.** Two commits:
|
||||
1. Add `magnotia_storage::Error`, `From<storage::Error> for MagnotiaError`, keep the old `StorageError(String)` variant temporarily as a no-op (compile-only).
|
||||
1. Add `lumotia_storage::Error`, `From<storage::Error> for MagnotiaError`, keep the old `StorageError(String)` variant temporarily as a no-op (compile-only).
|
||||
2. Remove the old `StorageError(String)` variant; all consumers now go through `Storage { ... }`.
|
||||
|
||||
Two commits means we can verify the type-system migration is sound before deleting the safety net.
|
||||
@@ -369,10 +369,10 @@ Once the migration lands:
|
||||
|
||||
```
|
||||
cargo fmt --all -- --check
|
||||
cargo check -p magnotia-storage
|
||||
cargo check -p magnotia-core
|
||||
cargo check -p lumotia-storage
|
||||
cargo check -p lumotia-core
|
||||
cargo check --workspace --all-targets
|
||||
cargo test -p magnotia-storage
|
||||
cargo test -p lumotia-storage
|
||||
cargo test --workspace --lib
|
||||
rg 'StorageError\(' crates/ src-tauri/src/ # must be zero
|
||||
rg 'Other\(String\)' crates/ src-tauri/src/ # must remain zero
|
||||
|
||||
@@ -145,7 +145,7 @@ Each area is independent. They can be tackled in any order, but the suggested or
|
||||
- `crates/audio/src/streaming_resample.rs` — extend `#[cfg(test)]` module
|
||||
- Likely also `crates/transcription/src/streaming/rms_vad.rs` — VAD has equally testable invariants
|
||||
|
||||
**Acceptance:** `cargo test -p magnotia-audio` includes property tests. Property tests have run with at least 1000 cases per invariant.
|
||||
**Acceptance:** `cargo test -p lumotia-audio` includes property tests. Property tests have run with at least 1000 cases per invariant.
|
||||
|
||||
### E. Frontend/backend error boundary cleanup
|
||||
|
||||
@@ -189,19 +189,19 @@ if [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then
|
||||
export GDK_BACKEND="${GDK_BACKEND:-x11}"
|
||||
export WINIT_UNIX_BACKEND="${WINIT_UNIX_BACKEND:-x11}"
|
||||
fi
|
||||
exec /usr/lib/magnotia/magnotia-bin "$@"
|
||||
exec /usr/lib/lumotia/lumotia-bin "$@"
|
||||
```
|
||||
|
||||
Per-format wrapper locations:
|
||||
|
||||
- `.deb` / `.rpm`: ship the wrapper as `/usr/bin/magnotia`; binary lives elsewhere.
|
||||
- `.deb` / `.rpm`: ship the wrapper as `/usr/bin/lumotia`; binary lives elsewhere.
|
||||
- AppImage: `AppRun` is the wrapper.
|
||||
- Flatpak: wrapper under `/app/bin/`; the manifest's `command` points at it.
|
||||
|
||||
**Fallback — static `.desktop` `Exec`:**
|
||||
|
||||
```desktop
|
||||
Exec=env WEBKIT_DISABLE_DMABUF_RENDERER=1 GDK_BACKEND=x11 WINIT_UNIX_BACKEND=x11 magnotia %U
|
||||
Exec=env WEBKIT_DISABLE_DMABUF_RENDERER=1 GDK_BACKEND=x11 WINIT_UNIX_BACKEND=x11 lumotia %U
|
||||
```
|
||||
|
||||
User-set values do not win through this path (the `env` invocation hardcodes them in the child env). Document the terminal-launch override path in user-facing docs.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
name: Phase 8 — Forgiving gamification (design)
|
||||
description: Design spec for Magnotia Phase 8. Surfaces today's completion count and a 7-day momentum sparkline on the Tasks header. No streaks, no grace days, no loss language.
|
||||
description: Design spec for Lumotia Phase 8. Surfaces today's completion count and a 7-day momentum sparkline on the Tasks header. No streaks, no grace days, no loss language.
|
||||
type: spec
|
||||
tags: [spec, phase-8, magnotia, tasks, gamification]
|
||||
tags: [spec, phase-8, lumotia, tasks, gamification]
|
||||
created: 2026/04/24
|
||||
status: approved
|
||||
phase: 8
|
||||
roadmap: docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md
|
||||
roadmap: docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md
|
||||
author: Wren (CORBEL's resident agent) on behalf of Jake Sames
|
||||
---
|
||||
|
||||
@@ -92,7 +92,7 @@ Query groups matching rows by local-day and then left-joins against a generated
|
||||
// - window focus (for day rollover while the app stayed open overnight)
|
||||
```
|
||||
|
||||
**Why not hook off `magnotia:task-completed` alone:** that event only fires on completion, not on uncomplete or delete, and relying on it would leave the badge stale after either of those paths. Refreshing at the mutation-helper level captures every path that can change today's count.
|
||||
**Why not hook off `lumotia:task-completed` alone:** that event only fires on completion, not on uncomplete or delete, and relying on it would leave the badge stale after either of those paths. Refreshing at the mutation-helper level captures every path that can change today's count.
|
||||
|
||||
**`src/lib/pages/TasksPage.svelte` header:**
|
||||
Stacks to:
|
||||
@@ -150,7 +150,7 @@ Only the sparkline respects the toggle. The badge is always on.
|
||||
- Migration v13: applies cleanly against a DB populated at v12; default of `auto_completed = 0` on pre-existing rows verified.
|
||||
|
||||
### Frontend (`npm run check` + vitest)
|
||||
- `completionStats` store refreshes on `magnotia:task-completed` event.
|
||||
- `completionStats` store refreshes on `lumotia:task-completed` event.
|
||||
- `todayCount` derives from the last entry.
|
||||
- Sparkline renders exactly 7 bars for a populated fixture.
|
||||
- Sparkline hidden when `showMomentumSparkline === false`.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
name: Phase 9 — Polish debt (design)
|
||||
description: Design spec for Magnotia Phase 9. Closes six polish-debt items from the feature-complete roadmap plus the Phase 8 carryover backlog. File-system save dialog, bulk History export, on-demand LLM content tags, progressive-disclosure Settings restructure, visual polish, accessibility sweep.
|
||||
description: Design spec for Lumotia Phase 9. Closes six polish-debt items from the feature-complete roadmap plus the Phase 8 carryover backlog. File-system save dialog, bulk History export, on-demand LLM content tags, progressive-disclosure Settings restructure, visual polish, accessibility sweep.
|
||||
type: spec
|
||||
tags: [spec, phase-9, magnotia, polish, accessibility, settings, export, llm]
|
||||
tags: [spec, phase-9, lumotia, polish, accessibility, settings, export, llm]
|
||||
created: 2026/04/24
|
||||
status: approved
|
||||
phase: 9
|
||||
roadmap: docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md
|
||||
roadmap: docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md
|
||||
author: Wren (CORBEL's resident agent) on behalf of Jake Sames
|
||||
---
|
||||
|
||||
@@ -18,7 +18,7 @@ Close the last polish-debt items before Phase 10 (QC + rename + release). Six it
|
||||
|
||||
1. **File-system `.md` save dialog** — replaces clipboard-only export on HistoryPage + DictationPage + FilesPage.
|
||||
2. **Bulk select + bulk export in History** — multi-select rows, export as a directory of `.md` files.
|
||||
3. **LLM content tags** — on-demand `topic:*` + `intent:*` extraction using `magnotia-llm`, persisted on history rows.
|
||||
3. **LLM content tags** — on-demand `topic:*` + `intent:*` extraction using `lumotia-llm`, persisted on history rows.
|
||||
4. **Settings UX overhaul** — progressive disclosure. High-frequency settings always-visible; advanced behind `<details>` groups. Phase 8 sparkline toggle relocated out of Rituals.
|
||||
5. **Visual polish pass** — spacing, typography, motion curves, dark-mode parity. Absorbs Phase 8 motion backlog on badge + sparkline.
|
||||
6. **Accessibility pass** — keyboard navigation, focus order, screen reader labels (friendlier sparkline aria copy), WCAG AA contrast. Absorbs Phase 8 a11y backlog.
|
||||
@@ -298,9 +298,9 @@ Natural split for the plan: 9a (items 1 + 2), 9b (item 3), 9c (item 4), 9d (item
|
||||
|
||||
## Anchors
|
||||
|
||||
- Roadmap: [docs/roadmap/2026-04-23-magnotia-feature-complete-roadmap.md](../../roadmap/2026-04-23-magnotia-feature-complete-roadmap.md)
|
||||
- Roadmap: [docs/roadmap/2026-04-23-lumotia-feature-complete-roadmap.md](../../roadmap/2026-04-23-lumotia-feature-complete-roadmap.md)
|
||||
- Phase 8 plan + spec + handover — for task-format reference and carryover backlog.
|
||||
- Phase 8 gotchas to respect in this phase:
|
||||
- `$derived` does not export at `.svelte.ts` module scope — use `export function` instead.
|
||||
- `#[derive(sqlx::FromRow)]` is not available in `magnotia-storage` (no change in Phase 9, but noted if schema work drifts there).
|
||||
- `#[derive(sqlx::FromRow)]` is not available in `lumotia-storage` (no change in Phase 9, but noted if schema work drifts there).
|
||||
- Progressive-disclosure pattern reference: NN/g on progressive disclosure; Material Design settings patterns; UX Collective on settings redesign.
|
||||
|
||||
@@ -35,7 +35,7 @@ The Apple "30% perf for 50% power" framing is empirical, not a published softwar
|
||||
|
||||
- **New** `crates/core/src/power.rs` — `PowerState`, sysfs probe, TTL cache.
|
||||
- **New** `crates/core/src/tuning.rs` — `Workload`, `inference_thread_count(workload, gpu_offloaded)`.
|
||||
- **Move** `vulkan_loader_available()` from `src-tauri/src/commands/models.rs` to `magnotia_core::hardware`. `crates/transcription` needs to call it; src-tauri continues to call it from its new home. `libloading = "0.8"` becomes a workspace dependency of `magnotia-core`.
|
||||
- **Move** `vulkan_loader_available()` from `src-tauri/src/commands/models.rs` to `lumotia_core::hardware`. `crates/transcription` needs to call it; src-tauri continues to call it from its new home. `libloading = "0.8"` becomes a workspace dependency of `lumotia-core`.
|
||||
- **Update** `crates/transcription/src/whisper_rs_backend.rs` — compute `gpu_offloaded`, pass to helper.
|
||||
- **Update** `crates/llm/src/lib.rs` — compute `gpu_offloaded`, pass to helper. (Recompute *after* the model loads, since `model.n_layer()` requires the loaded model.)
|
||||
- **Deprecate facade** `crates/core/src/constants.rs::inference_thread_count()` — keep as `#[deprecated]` re-export pointing at `tuning::inference_thread_count` for one commit, then remove.
|
||||
@@ -149,7 +149,7 @@ let gpu_offloaded = use_gpu
|
||||
|
||||
```rust
|
||||
let gpu_offloaded = cfg!(feature = "whisper-vulkan")
|
||||
&& magnotia_core::hardware::vulkan_loader_available();
|
||||
&& lumotia_core::hardware::vulkan_loader_available();
|
||||
```
|
||||
|
||||
Compile-time feature check (`whisper-vulkan` is in default features) plus runtime libvulkan resolution. If libvulkan1 isn't installed, whisper-rs falls back to CPU and we should not under-thread.
|
||||
@@ -227,6 +227,6 @@ inference_thread_count: 3 workload=Whisper gpu_offloaded=false on_battery=true c
|
||||
|
||||
- All four panels of `thread_sweep.rs` print without panic on a 6c12t Ryzen.
|
||||
- New unit tests pass on Linux (and on macOS CI where applicable; sysfs tests cfg-gated to Linux).
|
||||
- Existing `cargo test -p magnotia-core` and `-p magnotia-llm` continue to pass.
|
||||
- Existing `cargo test -p lumotia-core` and `-p lumotia-llm` continue to pass.
|
||||
- A real Lumenote session with on-battery laptop logs `on_battery=true clamps=[battery]` at first inference call.
|
||||
- Manual smoke: kick a Whisper Tiny transcription on battery, verify CPU usage settles around half what it was on AC.
|
||||
|
||||
Reference in New Issue
Block a user