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>
8.0 KiB
name, type, slice, last_verified
| name | type | slice | last_verified |
|---|---|---|---|
| Tasks and decomposition | architecture-map-page | 02-tauri-runtime | 2026/05/09 |
commands::tasks
Where you are: Architecture map → Tauri runtime → Commands → Tasks
Plain English summary. Eleven commands wrapping the lumotia_storage task CRUD plus two LLM-driven actions. Standard CRUD: create / list / update / complete / uncomplete / delete a task, plus subtask CRUD (insert / list / complete) and a daily-completion-counts query for the Phase 8 Tasks-page momentum sparkline. The two LLM actions: decompose_and_store (break a parent task into subtasks via the local LLM with HITL feedback as few-shot exemplars) and extract_tasks_from_transcript_cmd (extract task lines from a recently-finished transcript, again with feedback exemplars).
At a glance
- Path:
src-tauri/src/commands/tasks.rs. - LOC: 402.
- Tauri commands exposed (11 total):
create_task_cmd(state, request: CreateTaskRequest) -> Result<TaskDto, String>.list_tasks_cmd(state) -> Result<Vec<TaskDto>, String>.update_task_cmd(state, id, patch: UpdateTaskRequest) -> Result<TaskDto, String>. Patch shape (text / bucket / list_id / effort / notes).complete_task_cmd(state, id) -> Result<(), String>. Stamps server-sidedone_at.delete_task_cmd(state, id) -> Result<(), String>.uncomplete_task_cmd(state, id) -> Result<(), String>. Clearsdone_at.set_task_energy_cmd(state, id, energy: Option<String>) -> Result<TaskDto, String>. Always writes; passesNoneto clear.decompose_and_store(state, parent_task_id, profile_id) -> Result<Vec<TaskDto>, String>.extract_tasks_from_transcript_cmd(state, transcript, profile_id) -> Result<Vec<String>, String>.list_subtasks_cmd(state, parent_task_id) -> Result<Vec<TaskDto>, String>.complete_subtask_cmd(state, subtask_id) -> Result<(), String>.list_recent_completions_cmd(state, days) -> Result<Vec<DailyCompletionCount>, String>.
- Events emitted: none.
- Depends on:
lumotia_storage::{insert_task, list_tasks, update_task, complete_task, uncomplete_task, delete_task, set_task_energy, get_task_by_id, insert_subtask, list_subtasks, complete_subtask_and_check_parent, list_recent_completions, list_feedback_examples, FeedbackTargetType, TaskRow, DailyCompletionCount, FeedbackRow},lumotia_llm::prompts::FeedbackExample,uuid::Uuid. - Called from frontend at: Tasks page (CRUD, subtasks, sparkline), dictation result panel ("Extract tasks" button), parent-task expand UI ("Decompose").
What's in here
TaskDto (src-tauri/src/commands/tasks.rs:24)
camelCase frontend shape with id, text, bucket, listId, effort, notes, done, doneAt, createdAt, sourceTranscriptId, parentTaskId, energy.
Energy validation (:60)
ENERGY_LEVELS = ["high", "medium", "brain_dead"] — kept as a const so frontend and storage validate against the same set. SQLite migration v11 enforces the same set with a CHECK constraint.
CRUD wrappers
create_task_cmd(:92) inserts and re-fetches so the frontend gets the canonical row (server-side timestamps, defaulted columns).update_task_cmd(:140) — patch shape, COALESCE-style updates in storage.done/doneAtare deliberately absent — those flow throughcomplete_task_cmd/uncomplete_task_cmd.set_task_energy_cmd(:200) — separate from update because update usesCOALESCEsemantics whereNonemeans "preserve". This command always writes, so passingNoneactually clears the column.
to_llm_examples (:222)
Converts feedback rows from storage into the few-shot exemplar shape the LLM crate consumes. Reconstructs input from context_json (parent task text or transcript chunk). Rows with malformed context_json are logged and dropped instead of silently filtered, so data-integrity regressions surface.
example_char_cost (:263) and trim_to_budget (:276)
Char budget for the few-shot exemplars: keeps the prompt under token budget regardless of how many feedback rows the user has accumulated. Cap at 5 examples AND a char budget.
decompose_and_store (:290)
- Fetch the parent task or 404.
- Pull up to 5 micro-step feedback exemplars filtered by profile, char-trimmed.
spawn_blockingrunsengine.decompose_task_with_feedback(parent_text, &examples).- Insert each generated step as a subtask (
uuid::v4()for the id), re-fetch, accumulate. - Return the list.
NO PowerAssertion::begin here — the App Nap pattern is consistent in commands::llm but not yet uniformly applied here. Flag for follow-up.
extract_tasks_from_transcript_cmd (:345)
Same shape as decompose_and_store but with FeedbackTargetType::TaskExtraction and the engine's extract_tasks_with_feedback. Returns the raw task strings — the frontend decides whether to insert them.
list_subtasks_cmd / complete_subtask_cmd (:370, :381)
complete_subtask_cmd calls complete_subtask_and_check_parent which is the storage helper that stamps the subtask done and, if all siblings are done, also stamps the parent (Phase 8 micro-completion bookkeeping).
list_recent_completions_cmd (:394)
Fixed-length oldest-first daily counts. Empty days are explicit zeros. The Tasks-page sparkline reads this directly.
Data flow
Tasks page mount -> list_tasks_cmd -> [TaskDto, ...]
Tasks page create -> create_task_cmd(req) -> TaskDto
Tasks page edit -> update_task_cmd(id, patch) -> TaskDto
Tasks page check -> complete_task_cmd(id) -> ()
Tasks page reopen -> uncomplete_task_cmd(id) -> ()
Tasks page energy chip -> set_task_energy_cmd(id, energy) -> TaskDto
Tasks page sparkline -> list_recent_completions_cmd(days) -> [{date, count}, ...]
Tasks page Decompose button -> decompose_and_store(parent_id, profile_id)
-> get parent task
-> list 5 micro-step feedback rows (profile-scoped)
-> trim_to_budget
-> spawn_blocking(engine.decompose_task_with_feedback)
-> insert subtasks
-> [TaskDto, ...]
Dictation panel Extract tasks -> extract_tasks_from_transcript_cmd(text, profile_id)
-> list 5 task-extraction feedback rows
-> spawn_blocking(engine.extract_tasks_with_feedback)
-> [String, ...]
Watch-outs
- No
ensure_main_windowguard. Tasks UI lives in the main window AND in the always-on-top task float (which has the secondary-windows capability). The float can call list / complete / set-energy / list-recent-completions etc. — that's intentional — but it can also firedecompose_and_storeandextract_tasks_from_transcript_cmd, which spend LLM tokens. If you want to lock this down, add the guard to the LLM-spending commands. - No
PowerAssertion.decompose_and_storeandextract_tasks_from_transcript_cmdboth run synchronous LLM inference for several seconds. macOS can App Nap them. AddPowerAssertion::begin("lumotia LLM task decomposition")and similar. - The patch shape passes
Option<String>for every column. Currently the storage layer'supdate_taskuses COALESCE:Someoverwrites,Nonepreserves. This means there's no way to clearnotesoreffortto empty viaupdate_task_cmd— you can only set them to a non-empty string. If a user wants to clear a field, they'd need a fresh task or a dedicated clear command. - Decompose stores subtasks one-by-one in a loop (
:329). Each iteration is a separate DB transaction. Acceptable for typical 3–7-step decompositions; if a future LLM produces 50 steps, batch the inserts. extract_tasks_from_transcript_cmdreturns justVec<String>and does NOT insert. Frontend chooses what to insert. Confusing because the siblingdecompose_and_storedoes insert. Convention is dictated by UX (decomposition is one-click, extraction reviews-then-inserts).
See also
- LLM — the engine that runs the decomposition / extraction.
- Feedback — the table that feeds the few-shot exemplars.
- Profiles —
profile_idis the scoping key for feedback rows. - Window management — the task-float window (
tasks-float) that consumeslist_tasks_cmd.