docs: architecture map (initial 5-slice generation, 105 pages)
Five-slice navigable map of the entire codebase under
docs/architecture-map/. Each slice is a self-contained
breadcrumbed sub-tree:
01-frontend (16) Svelte/SvelteKit UI
02-tauri-runtime (26) src-tauri commands + lifecycle
03-audio-transcription (16) audio + transcription crates
04-llm-formatting-mcp (19) llm, ai-formatting, mcp, cloud
05-core-storage-hotkey-build core, storage, hotkey, workspace,
(26) CI, dev glue
Plus master README.md and data-flow-end-to-end.md tracing
audio bytes from microphone to FTS5 search to MCP read.
Generated by 5 parallel subagents on 2026/05/09 against
HEAD 3c47000. Each page has YAML frontmatter, file:line code
refs, sibling cross-links, plain-English summaries.
Aggregated debt surfaced (full lists in master README):
RB-08 macOS power assertion, schema head drift v14 vs v15,
VAD blocked on ort version conflict, streaming primitives
not wired into live.rs, no prompt versioning, MCP has no
auth, cloud-providers in-memory keystore, SettingsPage
2 484 LOC, commands/live.rs 1 737 LOC, dual theme system,
brand rename to Lumenote pending across the codebase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
119
docs/architecture-map/02-tauri-runtime/commands/tasks.md
Normal file
119
docs/architecture-map/02-tauri-runtime/commands/tasks.md
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
name: Tasks and decomposition
|
||||
type: architecture-map-page
|
||||
slice: 02-tauri-runtime
|
||||
last_verified: 2026/05/09
|
||||
---
|
||||
|
||||
# `commands::tasks`
|
||||
|
||||
> **Where you are:** [Architecture map](../../README.md) → [Tauri runtime](../README.md) → [Commands](README.md) → Tasks
|
||||
|
||||
**Plain English summary.** Eleven commands wrapping the `magnotia_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-side `done_at`.
|
||||
- `delete_task_cmd(state, id) -> Result<(), String>`.
|
||||
- `uncomplete_task_cmd(state, id) -> Result<(), String>`. Clears `done_at`.
|
||||
- `set_task_energy_cmd(state, id, energy: Option<String>) -> Result<TaskDto, String>`. Always writes; passes `None` to 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: `magnotia_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}`, `magnotia_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` / `doneAt` are deliberately absent — those flow through `complete_task_cmd` / `uncomplete_task_cmd`.
|
||||
- `set_task_energy_cmd` (`:200`) — separate from update because update uses `COALESCE` semantics where `None` means "preserve". This command always writes, so passing `None` actually 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`)
|
||||
|
||||
1. Fetch the parent task or 404.
|
||||
2. Pull up to 5 micro-step feedback exemplars filtered by profile, char-trimmed.
|
||||
3. `spawn_blocking` runs `engine.decompose_task_with_feedback(parent_text, &examples)`.
|
||||
4. Insert each generated step as a subtask (`uuid::v4()` for the id), re-fetch, accumulate.
|
||||
5. 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_window` guard.** 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 fire `decompose_and_store` and `extract_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_store` and `extract_tasks_from_transcript_cmd` both run synchronous LLM inference for several seconds. macOS can App Nap them. Add `PowerAssertion::begin("magnotia LLM task decomposition")` and similar.
|
||||
- **The patch shape passes `Option<String>` for every column.** Currently the storage layer's `update_task` uses COALESCE: `Some` overwrites, `None` preserves. This means there's no way to clear `notes` or `effort` to empty via `update_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_cmd` returns just `Vec<String>` and does NOT insert.** Frontend chooses what to insert. Confusing because the sibling `decompose_and_store` *does* insert. Convention is dictated by UX (decomposition is one-click, extraction reviews-then-inserts).
|
||||
|
||||
## See also
|
||||
|
||||
- [LLM](llm.md) — the engine that runs the decomposition / extraction.
|
||||
- [Feedback](feedback.md) — the table that feeds the few-shot exemplars.
|
||||
- [Profiles](profiles.md) — `profile_id` is the scoping key for feedback rows.
|
||||
- [Window management](windows.md) — the task-float window (`tasks-float`) that consumes `list_tasks_cmd`.
|
||||
Reference in New Issue
Block a user