Phase 0 update: replaces the loose "quick wins" list with a structured
Fix Areas section organised into impact tiers (A: high-impact README
truth fixes, B: low-effort self-violation fixes, C: structural smells
deferred to Phase 2, D: hygiene). Each task names the file, the change,
the verification command, and the effort estimate.
New playbook: docs/audit/phases-1-8-playbook.md — step-by-step
acquisition-grade audit procedure for the remaining seven phases. Each
phase has goal, inputs, procedure (with concrete commands), deliverable,
acceptance criteria, and time estimate. Designed to be picked up
independently from any phase.
Inventory of workspace shape, LOC, dependency graph, public API surface,
external surfaces (Tauri commands / MCP tools / frontend routes), and a
README↔code drift log. Input for Phase 1 (lean-pass).
Surfaces five concrete README drifts (one HIGH: stores list fiction; two
MED: undocumented Tauri modules and a Moonshine claim with no registry
entry) and three structural smells worth a Phase-2 follow-up.
Replace all instances of the legacy product names "Kon" and "Corbie" with
"Magnotia" across user-facing copy, code identifiers, package names, bundle
ids, file paths, and documentation. Preserves the unrelated "konsole" (KDE
terminal) reference and the parent CORBEL company name.
- Renames 10 Rust crates (kon-* → magnotia-*) and the tauri binary
- Updates package.json, tauri.conf.json (productName + identifier)
- Renames CSS classes (kon-rh-* → magnotia-rh-*) and animations
- Renames brand and roadmap docs
- Regenerates Cargo.lock and package-lock.json
Verified: svelte-check passes; pure-rust crates compile under new names.
Captures the agent-runnable portion of Phase 10a ahead of Jake's
manual walkthrough and feedback-document pass:
- a11y baseline confirmed clean (svelte-check 0/0; consistent
aria-label + aria-hidden patterns across icon buttons; global
:focus-visible ring set in design tokens; prefers-reduced-motion
guards present where motion warrants them)
- WCAG 2.1 AA contrast tables for both themes computed from the
token list at design-system/colors_and_type.css. Nine pairs miss
AA-normal; light-theme warning misses AA-large too. Severity
ranked, suggested token shifts noted as starting points
- CI matrix state: check.yml runs on every push, build.yml has
never been end-to-end exercised - recommend manual workflow_
dispatch before tagging v0.1.0
- Clean-install test plan and the Phase 9d walkthrough checklist
consolidated for the testing session
Phase 9 export plumbing, LLM content tags (with migration v14 + storage
+ Tauri-command extension that picks up the latent manualTags
persistence bug as a side effect), and sparkline polish all on main.
SettingsPage deeper restructure and walkthrough-driven a11y sweeps
deferred to a follow-up polish session and Phase 10a QC respectively.
Roadmap Phase 9 entry updated with shipped + deferred notes. HANDOVER
captures the full session including the plan-correction discovery and
the Codex-blocked retries. Phase 8 handover preserved as the dated
archive HANDOVER-2026-04-24.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-execution review against the actual codebase (Codex unavailable
this session) surfaced three mismatches: kon-llm uses LlmEngine with a
synchronous generate(prompt, config), AppState exposes llm_engine as a
direct Arc not behind RwLock, and llmTags persistence requires a real
SQLite migration plus Tauri command extension because saveHistory()
is a no-op stub today (which also means manualTags edits weren't
persisting). Plan now adds Task 8.5 for migration v14 + storage and
Tauri-command extension. Spec data-model section corrected to match.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sixteen tasks across four sub-phases (9a export plumbing, 9b LLM tags,
9b Settings restructure, 9d polish and a11y). TDD task structure for
the concrete items (save dialog, LLM extraction, types/persistence);
discovery-and-checklist structure for the polish items where an
a-priori test is not meaningful. Commit cadence matches Phase 8 (one
commit per task, feat/fix/polish prefix tags).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Roadmap: Phase 8 header now carries SHIPPED 2026/04/24 alongside the
REVISED 2026/04/23 marker. Added a shipped note summarising the
landing commits, architectural deltas, and verification state.
Pre-Phase-10 Cargo.lock decision updated to RESOLVED since Jake's
hardening pass (commit b333c62) committed the lockfile.
HANDOVER rewritten for today's state. Covers Phase 8 end-to-end,
counting semantics, three architectural notes worth carrying forward
(serde in kon-storage; no module-scope $derived export; tuple FromRow
pattern), full verification counts, the manual dogfood walkthrough
still owed to Jake when he next opens Corbie, and a Phase 9 polish
backlog surfaced during review (sparkline aria-label summary form,
sparkline toggle placement inside Rituals section).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
13 bite-sized tasks with TDD on the Rust side (migrations +
cascade flag + list_recent_completions query + 4 storage tests) and
incremental frontend wiring (store, sparkline component, Tasks header
badge, event dispatches, settings toggle). Verification pass + roadmap
and HANDOVER update as final tasks.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Covers today's completion count badge + 7-day momentum sparkline on the
Tasks header. Chose to exclude auto-cascade parents from the count via a
new auto_completed column (migration v13), to respect the zero-loss
framing. Sparkline is a new settings toggle, default on.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three opt-in rituals, all default OFF. Research-anchored (Barkley's
point-of-performance, Sweller cognitive-load theory, Newport shutdown
ritual, Gollwitzer implementation intentions, Thaler/Sunstein nudge
with informed consent for the ADHD audience).
Morning triage: modal gated on ritualsMorning toggle, configurable
trigger time (default 08:00 to respect ADHD sleep inertia rather than
the spec's 06:00), "pick up to three for today" with a gentle swap
message on the fourth attempt. Skip sets last-shown-today so it never
re-prompts the same calendar day. last-shown persists via kon_storage.
Evening wind-down: dedicated page, user-triggered only (tray menu +
Settings button). Mechanical closure + physical reset + intentional
cue — the whole Newport template. Open loops are read-only reflection;
Tasks page owns transactions. Copy is additive throughout: "you
finished X today", never "you didn't finish Y".
Autostart: tauri-plugin-autostart registered (LaunchAgent on macOS,
.desktop on Linux, registry Run on Windows). No bespoke Rust commands
— frontend calls the plugin's invoke-handlers directly. Toggle in
Settings is one-way (click → OS call → state update) to avoid the UI
lying during the round-trip. First-run presents a forced-choice prompt
for all three options, with "skip all" escape hatches per step.
Copy audit against RSD literature: no "overdue", "failed", or
day-to-day comparison framing anywhere in ritual surfaces.
Post-v0.1 ideas captured in the roadmap: calendar integration
(read-only ICS as interim, cloud sync parked) and right-click-to-task
(in-app simple, system-wide a separate phase).
The accumulator task was fire-and-forget — `tokio::spawn` without
retaining the JoinHandle. `stop_native_capture` sent a stop signal,
slept 50ms, and returned; the worker could still be running its
final flush and appending to `all_samples` when the next
`start_native_capture` cleared it. Rapid start→stop→start could
leak tail samples from one session into another.
Replace `NativeCaptureState.stop_tx` with `worker:
AsyncMutex<Option<CaptureWorker>>`, where CaptureWorker owns both
the stop sender and the spawned task's JoinHandle. New helper
`stop_worker(worker)` sends stop, drops the sender, and `.await`s
the join. Both the prior-worker tear-down in `start_native_capture`
and `stop_native_capture` itself go through the helper, so the
worker is always fully terminated before any downstream read or
next-session cleanup.
AsyncMutex (not std::sync::Mutex) because the stop path awaits
while holding the lock. Also drops the 50ms sleep from
stop_native_capture — the join is an exact barrier.
Two regression tests:
- stop_worker_awaits_full_termination_no_writes_after_join:
synthetic worker with an atomic counter and a flush marker.
After stop_worker the flush must have run and no further
writes may appear.
- stop_worker_is_idempotent_on_a_worker_that_has_already_exited:
tasks that stop themselves must still join cleanly.
A full cpal-backed start→stop→start integration test is not
feasible in Linux CI without an audio device. The component tests
cover the invariant the real flow depends on.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
get_runtime_capabilities was returning `accelerators = ["cpu",
"vulkan"]` and `whisper.supports_gpu = true` regardless of build
config or runtime state. On a macOS build it falsely advertised
"vulkan" (the backend actually resolves via MoltenVK as Metal); on a
whisper-disabled build it claimed GPU support for an engine that
hadn't been linked.
Added `compose_accelerators(whisper_enabled, loader_available, target)`
— a pure helper that always emits "cpu" first and appends the
platform-appropriate GPU name only when whisper is compiled in AND the
Vulkan loader resolves. `supported_accelerators()` wraps it with the
live `cfg!(feature = "whisper")`, loader probe, and target OS.
`get_runtime_capabilities` now calls `supported_accelerators()` and
sets `whisper.supports_gpu = cfg!(feature = "whisper")`. Parakeet
stays CPU-only.
Five tests in `commands::models::tests` cover the permutation matrix:
whisper on/off, loader present/missing, macOS vs other. Both feature
configurations (`--features whisper` and `--no-default-features`)
build and pass tests.
Macos Metal-loader resolution on real hardware stays on the
ship-gate checklist — the detection logic is verifiable from Linux
but runtime behaviour is not.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Every multi-statement migration and its matching schema_version insert
now execute on the same sqlx Transaction. A failure anywhere — a bad
statement, the version insert, or the commit itself — rolls the
database back to its previous state, so the next startup replays the
migration against a clean schema rather than a half-mutated one.
Extracted run_migrations_slice(pool, migrations) as the single apply
path. run_migrations delegates to it with MIGRATIONS; the test helper
run_migrations_up_to now filters MIGRATIONS by target and delegates to
the same code, eliminating the duplicated loop that previously lived
in the test module.
Regression test multi_statement_migration_rolls_back_on_failure
injects a poisoned v9 migration (valid CREATE followed by a bogus
function call) and asserts neither the partial schema change nor the
schema_version row persists after the failure.
SQLite DDL participates in transactions, so this is sufficient. Any
future migration that needs an implicitly-committing statement
(VACUUM / REINDEX / ATTACH — none today) must be its own
non-transactional migration; that's a reviewer responsibility.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
decode_audio_file's packet loop was `Err(_) => break`, so any non-EOF
read error during playback dropped out silently with whatever samples
had accumulated. Per-packet decode errors were tallied and skipped,
contributing to the same outcome. A corrupt or truncated input
therefore came back as `Ok(partial_samples)` — no way for callers to
distinguish a clean decode from a compromised one.
Every SymphoniaError other than the explicit EOF
(`IoError(UnexpectedEof)`) now maps to `AudioDecodeFailed`. Decoder
errors bubble via `?` rather than being counted. `ResetRequired`
promotes to an error rather than a silent break.
Extracted an internal `decode_media_stream(mss, hint)` so tests can
inject a custom `MediaSource`. Added `FlakyCursor` — a seekable cursor
that returns a synthetic I/O error after N bytes — and a regression
test that confirms mid-stream read failure surfaces as `Err` instead of
returning partial audio. Happy-path and missing-file tests added for
coverage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
try_attach_device was rejecting any device that did not report KEY_A or
KEY_R — a leftover heuristic from the whisper-overlay seed. A user whose
binding was anything else (Ctrl+Shift+D is a common default) would see
no hotkey events from that device even though it supports the key.
Replace the hard-coded check with device_supports_combo(supported,
combo), a pure helper that reads the configured trigger key code from
the HotkeyCombo snapshot. Snapshot is taken from hotkey_rx.borrow()
before opening the device; an unconfigured or shutting-down listener
short-circuits to a non-attach.
Four regression tests in linux::tests cover: supported+D → attach,
unsupported → reject, no reported keys → reject, and the explicit
non-A/non-R case that demonstrates the bug.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Every issue under docs/issues/ links to this file as its Source. It was
created for 592b894 but not staged, leaving dangling links in the
release-blocker tracker.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures the 12 items from docs/code-review-2026-04-22.md that
must land before v0.1 ships. One markdown file per issue with:
severity, path:line, problem description, acceptance criteria,
fix scope, and dependency graph.
Split by severity:
- 3 CRITICAL: live-session race, migration atomicity, transcript-
profile FK
- 9 MAJOR: monolith refactor, channel-fatality, capture worker
join, runtime capabilities, macOS App Nap, decoder error prop,
LLM prompt preflight, keystore thread-safety, hotkey device
filter
README.md indexes them with a fix-order dependency graph and a
fish-shell script for bulk-converting to GitHub issues once `gh`
CLI is installed and authed. Deferred step by user decision —
markdown tracker is authoritative until then.
Sequences the 13 B-scope items from docs/whisper-ecosystem/brief.md
into three phases (pre-emptive UX, feature pinches, LLM layer) with
stop-for-review boundaries between each.
Enumerates the Settings sections touched per item (net: +2 toggles,
+2 sub-cards, nothing invisible becomes visible), the new
SettingsState fields with defaults, the schema migration bump
(version 1 -> 2), and the explicit Workstream A dependencies +
stubbed fallbacks for each (#14 list_gpus, #30 streaming cleanup,
#31 llm-state-change event).
Co-authored-by: jars <jakejars@users.noreply.github.com>
Sequences the 18 A-scope items from docs/whisper-ecosystem/brief.md
into four phases (pre-emptive patches, engine abstraction, streaming
correctness, LLM guard) with stop-for-review boundaries between each.
Lists the new command + event contracts (#1 activeComputeDevice,
#14 list_gpus/set_preferred_gpu, #24 tentative segment flag, #28
parallel-mode toggle) that Workstream B will consume.
Co-authored-by: jars <jakejars@users.noreply.github.com>
Specs the subset of the five-phase GPU kernel tuning roadmap that ships
without requiring ggml-dedup or agentic-search prerequisites:
- Phase 1 — Advanced → GPU Tuning settings panel (GGML env var toggles,
applied at startup before threads spawn).
- Phase 2 — kon-bench local autotuning CLI. Subprocess-based grid search
over env vars, outputs a ranked gpu-profile.toml.
- Phase 3-lite — kon-configs community repo. Manual-PR workflow (no CI
replay), fingerprint-matched fetch from Kon Settings.
Total ~7–10 days of focused work; captures roughly 85% of the eventual
value of the full roadmap. Phases 4–5 (custom SPIR-V drops + agentic
autotune) stay pinned in memory.
Includes the UX spec for the "one-click auto-optimise" flow: community
config check first (~15 s end-to-end), local benchmark fallback
(~8 min backgrounded), opt-in share-back via browser PR. Non-GPU users
see a clean "tuning doesn't apply" card with no nag.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cloud agents (Codex / Opus in Cursor) can't read the author's local
Claude memory directory. This doc folds the non-negotiable ideology,
architectural decisions, what's already shipped, what's intentionally
deferred, and the file-ownership fence between Workstream A and B into
a single in-repo reference.
Kickoff prompts now point agents at docs/whisper-ecosystem/kon-context.md
as the primary read BEFORE brief.md, so the agents understand what NOT
to re-implement (already-shipped features) and what NOT to touch (the
other workstream's territory, the ggml dedup interim, etc.).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Survey of 10 OSS Whisper projects (whisper.cpp, whisper-rs, Handy, Buzz,
Whispering/Epicenter, faster-whisper, WhisperLive, whisper_streaming,
Scriberr, Vibe, OpenWhispr). Pins the cross-repo pain pattern matrix,
feature inventory with priority tags, streaming-specific findings, LLM
formatting findings, and a 31-item atomic task backlog — all URL-sourced.
Lives in the repo as the canonical reference for the phase-4 implementation
pass. Both Cursor workstreams (Codex for systems + streaming, Opus for UX
+ LLM layer) read this at kickoff.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>