Files
Lumotia/HANDOVER.md
jars 2a45cb8033 fix: model-loaded guards on transcribe_pcm, power assertion guards on tasks LLM commands
transcribe_pcm and transcribe_pcm_parakeet did not check that their
respective engines were loaded before clone+spawn_blocking. transcribe_file
already calls ensure_model_loaded; these now mirror that posture with a
friendly error when the engine is unloaded, matching what
extract_content_tags_cmd does.

decompose_and_store and extract_tasks_from_transcript_cmd ran multi-second
LLM inference inside spawn_blocking without the PowerAssertion guard that
cleanup_transcript_text_cmd and extract_content_tags_cmd already use. Both
now begin a guard so the macOS App-Nap inhibitor (and the planned
Linux/Windows equivalents per KI-02, KI-03) can pin the process for the
duration of the inference.

HANDOVER.md gets a status note clarifying it captures Phase 9 state. The
schema head referenced (v14) was the head at session time; current head
is v15 (`idx_transcripts_profile_created` composite index) per the
architecture map.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 15:47:48 +01:00

12 KiB

name, type, tags, description
name type tags description
handover-2026-04-25 reference
handover
session
magnotia
phase-9
polish-debt
Session handover — 2026/04/24-25 Phase 9 polish debt mostly shipped

Magnotia Handover — 2026/04/25

Note: Session-specific handover. Migration v14 (transcripts.llm_tags) was the head at the time of this session. Subsequent work has advanced the schema; current head is v15 (idx_transcripts_profile_created, composite index). For the current codebase shape, see docs/architecture-map/ and KNOWN-ISSUES.md.

Phase 9 session. Spec + plan written from scratch and committed; plan corrections layered in after critical review against the actual codebase (Codex was unreachable for cross-model review, three retries failed at the ChatGPT-account-entitlement layer). Sub-phases 9a + 9b + sparkline polish landed end to end. Sub-phase 9c reduced to the Phase 8 carryover bug fix; sub-phase 9d's walkthrough sweeps deferred to Phase 10a QC.

Rebrand note

Product rename Magnotia → Magnotia still in flight. Copy in new docs is "Magnotia"; codebase paths / package names / repos still carry magnotia. No rebrand work this session. See ~/.claude/projects/-home-jake-Documents-CORBEL-Main/memory/project_magnotia_rebrand.md.

What shipped this session

9a — Export plumbing

  • write_text_file_cmd Rust command in new src-tauri/src/commands/fs.rs, with two unit tests (UTF-8 round-trip + bad-parent error path). Registered in invoke_handler!. tempfile = "3" added as [dev-dependencies] on the magnotia crate.
  • src/lib/utils/saveMarkdown.ts utility centralises suggestedFilename, saveTranscriptAsMarkdown, exportTranscriptsToDir (directory-mode bulk export with in-batch collision suffixing).
  • HistoryPage exportMarkdown no longer copies to clipboard; it opens the OS save dialog and writes the file. Cancel returns silently.
  • HistoryPage gained a slim leading checkbox per row, a bulk-action toolbar (select-all / clear / export / delete), Esc to clear, Cmd/Ctrl+A to select-all-visible when focus is inside the list and not in a text input.

9b — LLM content tags

  • magnotia-llm exports a new ContentTags { topic, intent }, an INTENT_CLOSED_SET, an is_valid_intent helper, a CONTENT_TAGS_SYSTEM prompt and a CONTENT_TAGS_GRAMMAR GBNF (recursive style matching the existing TASK_ARRAY_GRAMMAR).
  • LlmEngine::extract_content_tags method follows the same render-chat → generate → JSON-parse shape as the existing cleanup_text and extract_tasks. Truncates to the trailing 2000 chars on a UTF-8 boundary; max_tokens 96 is enough for the JSON envelope. Smoke test in crates/llm/tests/content_tags_smoke.rs is gated on MAGNOTIA_LLM_TEST_MODEL matching the Phase 8 pattern.
  • extract_content_tags_cmd Tauri wrapper bridges through state.llm_engine with the standard spawn_blocking + PowerAssertion guard.

9b structural — migration v14 + persistence wiring

A correction layered in after the critical-review pass discovered the original Task 9 was assuming a writable saveHistory() path that turned out to be a no-op stub.

  • Migration v14 adds transcripts.llm_tags TEXT NOT NULL DEFAULT ''.
  • magnotia-storage database.rs SELECT statements include the column. TranscriptRow + transcript_row_from carry it. update_transcript_meta accepts an Option<&str> for llm_tags (sixth optional, #[allow(too_many_arguments)] keeps clippy happy without inverting the signature into a struct).
  • commands/transcripts.rs TranscriptDto + UpdateTranscriptMetaRequest add llm_tags; update_transcript_meta_cmd forwards.
  • Frontend types: TranscriptEntry.llmTags: string[], TranscriptRow.llmTags: string, ContentTags, optional TranscriptMetaPatch.llmTags.
  • mapTranscriptRow hydrates llmTags. saveTranscriptMeta now also forwards llmTags payloads. buildFrontmatter unions auto + manual + LLM tags into the exported markdown frontmatter.
  • HistoryPage tag UI: per-row "Tag" button, dashed-italic LLM chips that promote-to-manual on click, top-toolbar "Tag all untagged" with progress text. Existing addManualTag / removeManualTag handlers swap their no-op saveHistory() calls for saveTranscriptMeta — picks up the latent manualTags persistence bug as a side effect.

9b incidental fix — Phase 8 brittle test

list_recent_completions_uses_local_day_boundary failed today because its UTC-anchored '-2 days', '+12 hours' offset drifts across UTC midnight relative to the local-day spine the query uses. Fixed by anchoring the timestamp to the local date 2 days ago directly: datetime(DATE('now', 'localtime', '-2 days') || ' 12:00:00'). Phase 9 was not the cause; the test happened to fail on today's clock.

9c — Settings (scaled down)

  • SettingsGroup.svelte reusable progressive-disclosure wrapper landed (animated chevron, hover, focus-visible, prefers-reduced-motion).
  • Sparkline toggle (Phase 8 carryover backlog) relocated from the Rituals section into a new dedicated "Tasks" section. Closes the Phase 8 review note that the toggle was visually claimed by the launch-at-login subgroup.
  • Deferred: the deeper restructure to seven progressive-disclosure groups + search box. The 2309-line SettingsPage.svelte uses a hand-rolled accordion that needs careful unwinding; full restructure was too invasive to land safely in this session. SettingsGroup component is in tree, ready for that follow-up pass.

9d — Polish (partial)

  • CompletionSparkline.svelte: friendlier sentence-form aria-label ("3 completed today. 14 total over the last 7 days." rather than a bare numeric list), per-bar <title> tooltips with absolute date + count, 30 ms staggered scaleY entrance animation. Earlier draft tabindex=0 on the SVG removed: role="img" + aria-label is sufficient for SR navigation without putting it in the keyboard tab order (svelte-check's noninteractive_tabindex warning, correctly).
  • TasksPage badge: 180 ms opacity + translate-Y entrance animation on conditional mount. Both new animations respect prefers-reduced-motion.
  • Deferred to Phase 10a QC: keyboard traversal walkthrough across every page, focus-visible ring sweep, WCAG AA contrast audit in both themes, dark-mode parity check, icon-only-button aria-label audit. These are walkthrough-driven and need a running dev server to validate.

Verification state at session end

Fresh run on main tip dd45f10:

  • cargo fmt --check: clean.
  • cargo clippy --all-targets -- -D warnings: clean.
  • cargo test: 277 tests pass, 0 failed. Storage gained 1 new test (update_transcript_meta_writes_llm_tags), magnotia-tauri gained 2 (write_text_file). The Phase 8 brittle test fix is in this count.
  • npm run check: 0 errors, 0 warnings across 3957 files.
  • npm run build: clean production build via @sveltejs/adapter-static.

Plan correction summary (for any future reader)

The original Phase 9 spec + plan committed at 49a795f + 48d3db7 had three mismatches against the actual codebase, surfaced by a critical-review pass before execution. Layered as a corrections appendix in commit 3eb24f2:

  1. magnotia-llm is LlmEngine::generate(prompt, config) synchronous, not the speculated LlamaEngine::generate_chat(messages, config).await.
  2. AppState.llm_engine: Arc<LlmEngine> is direct, not behind a RwLock.
  3. Structuraltranscripts.llm_tags requires a real SQLite migration plus Tauri command extension because the frontend saveHistory() is a no-op stub. Original plan assumed manualTags-mirroring would suffice. Migration v14 + update_transcript_meta extension landed as a new task to cover this. Picked up the latent manualTags persistence bug for free.

Owed to Jake (next session)

  1. Manual dogfood walkthrough. Cannot be driven by an automated agent. When opening Magnotia next:

    • Export one transcript via the History "Export .md" button — save dialog opens, file written to chosen path. Cancel — no toast, no fallback.
    • Select 3 history rows via checkboxes — toolbar surfaces, "Export selected" writes one .md per row to a chosen folder, collisions suffixed " (2)" etc.
    • Click "Tag" on one row — within a few seconds, dashed topic:* and intent:* chips appear. Click a chip — it moves into manualTags (solid accent chip). Page refresh — both manualTags and llmTags survive (this is the persistence-fix outcome).
    • "Tag all untagged" runs across the corpus, progress text updates, success toast at the end.
    • Settings → new "Tasks" section appears with the sparkline toggle. Toggle off → sparkline disappears on Tasks page; badge stays. Toggle on → sparkline returns.
    • Sparkline keyboard-focus-or-hover on a bar shows the date + count tooltip. Screen reader announces the sentence-form summary.
    • prefers-reduced-motion set in OS — badge entrance + sparkline stagger both stop.
  2. Phase 9 follow-up to absorb in a future polish session:

    • Full SettingsPage regroup using SettingsGroup (already in tree), search box, Start-here always-expanded, six collapsed groups by domain.
    • The walkthrough-driven a11y sweeps from Phase 9 Tasks 14-15. Phase 10a QC will catch most; document any issues for a follow-up polish commit.
  3. Codex unavailability. Three retries on the codex-rescue subagent failed because the local ~/.codex/config.toml pins model = "gpt-5.5" which the ChatGPT account doesn't have access to, and explicit overrides (gpt-4o, o4-mini, codex-mini-latest, gpt-5.3-codex-spark) are also blocked at the ChatGPT-account level. Either upgrade the ChatGPT plan tier or switch Codex auth to an OpenAI API key (codex login with key) to unblock cross-model review on future plans.

What's left for v0.1

Phase State
Phases 1-8 All shipped.
Phase 9 Mostly shipped this session. Export plumbing, LLM content tags (with persistence), polish on sparkline + badge are live. SettingsPage deeper restructure + walkthrough a11y sweeps deferred. Roadmap entry updated.
Phase 10a QC: dogfood walkthrough (above), Rachmann's RB-08 Mac verification (parallel), cross-platform CI, a11y regression, clean-install test. Half day.
Phase 10b Magnotia → Magnotia rename sweep: package name, all 10 crates, bundle ids, install paths, magnotia.dbmagnotia.db, event names, repo rename on both remotes. Half to 1 day.
Phase 10c Release: 0.1.0 version sync, CHANGELOG seeded from roadmap phases, release notes, tag + push. Half day.

Release-blocker state

  • 0 open CRITICAL.
  • 1 open MAJOR. RB-08 power-assertion-macos-objc2 (awaits Rachmann's manual runtime verification). Gates v0.1 tagging.

Repo state at session end

  • main at dd45f10.
  • 18 Phase 9 commits (3 docs + 15 feat/polish) on top of yesterday's tip.
  • Local branches: main only.
  • cargo build --workspace green / cargo test --workspace green (277 passing) / cargo clippy --workspace --all-targets -- -D warnings clean / cargo fmt --check clean / npm run check 0/0 / npm run build clean.

Anchors