Commit Graph

15 Commits

Author SHA1 Message Date
27661c816e agent: lumotia — pin rust toolchain + workspace clippy/fmt sweep
rust-toolchain.toml pins to stable 1.94.1 so contributors and CI runners
share the exact rustc / rustfmt / clippy versions. Without the pin, every
machine surfaces a different lint set depending on its local install — six
pre-existing lints showed up on 1.94.1 that 1.93-era HANDOVER reported clean.

Clippy fixes (all pre-existing, not introduced by feature work):

- crates/storage/src/database.rs: std::iter::repeat().take() -> repeat_n()
- crates/llm/src/lib.rs (docs): "+ frontends" was parsed as a markdown bullet
  continuation by rustdoc, breaking doc-lazy-continuation. Reworded to "and".
- crates/llm/src/lib.rs (loop): while-let-on-iterator -> for-loop.
- src-tauri/src/commands/security.rs: .iter().any(|a| *a == x) -> .contains(&x).
- src-tauri/src/lib.rs: io::Error::new(Other, e) -> io::Error::other(e).
- src-tauri/src/tauri_app_data_migration.rs: drop function-tail `return`s
  inside cfg blocks; each platform's block now ends with a tail expression.

cargo fmt sweep across the workspace. Mechanical layout-only changes;
no semantics affected.

Workspace gates after this commit:
- cargo fmt --check: clean
- cargo clippy --workspace --all-targets -- -D warnings: clean
- cargo test --workspace: 405/0 (will become 409/0 with Phase A.1+A.2)
2026-05-14 07:19:59 +01:00
094b533ef2 agent: code-atomiser-fix — surface capture-thread drops + bypass validation requeue cap
dropped_chunks was incremented on cpal-callback channel-full and
validation requeue overflow but never read by the live session, so
the UI's dropped_audio_ms missed callback-level losses entirely.
Architecture doc had flagged this as a TODO. Also: the 350ms
validation buffer was requeued via try_send into the same 32-slot
channel, silently dropping past the cap on small-buffer audio hosts
(WASAPI exclusive, low-latency ALSA at 256 frames -> ~65 chunks).

Fix: live runtime reads MicrophoneCapture::dropped_chunks() on each
recv_audio tick (LiveSessionRuntime::poll_capture_drops) and converts
the per-chunk-duration delta into the dropped_audio_ms surfaced to
the UI overload status. Per-chunk duration is derived from the most
recent AudioChunk's sample_rate + samples-per-channel so it adapts
to whatever rate cpal is delivering at. Validation requeue moved
from try_send into the bounded channel onto a VecDeque<AudioChunk>
returned alongside the Receiver; ActiveCapture drains the replay
buffer before reading rx in recv_audio, bypassing the 32-slot cap
entirely. Architecture doc updated to remove the TODO and document
the new pre-roll path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 14:39:14 +01:00
42f4d07e48 agent: lumotia-rebrand — drop MagnotiaError prefix, now lumotia_core::Error
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
Phase 3 of the rebrand cascade per locked decision D4. MagnotiaError ->
Error in crates/core/src/error.rs (the crate name already qualifies it).
92 usages across 14 .rs files renamed via word-boundary sed.

One collision required disambiguation: lumotia_storage already had its
own local Error type (introduced by the slop-pass Area A residuals work).
crates/storage/src/error.rs aliases the imported core error as CoreError
on import; the From<Error> for CoreError boundary impl and the
CoreError::Storage construction site use the alias.

cargo build --workspace passes. cargo test --workspace: 330 pass, 0 fail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 08:58:05 +01:00
089349d966 agent: lumotia-rebrand — rust workspace crates magnotia-* -> lumotia-*
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
Phase 2 of the rebrand cascade. Renames all 9 workspace crates from
magnotia-* to lumotia-* plus the src-tauri binary crate name:

- magnotia-ai-formatting   -> lumotia-ai-formatting
- magnotia-audio           -> lumotia-audio
- magnotia-cloud-providers -> lumotia-cloud-providers
- magnotia-core            -> lumotia-core
- magnotia-hotkey          -> lumotia-hotkey
- magnotia-llm             -> lumotia-llm
- magnotia-mcp             -> lumotia-mcp
- magnotia-storage         -> lumotia-storage
- magnotia-transcription   -> lumotia-transcription
- magnotia                 -> lumotia (src-tauri binary)
- magnotia_lib             -> lumotia_lib (src-tauri lib target)

Crate directories (crates/audio/ etc.) stay as-is; only the Cargo.toml
[package] name field changes plus all consumer module imports
(magnotia_core -> lumotia_core, etc.).

Remaining magnotia_* references at this point are intentional and
scoped to later phases: tracing targets (Phase 4), DB setting keys
magnotia_preferences/magnotia_history (Phase 5).

cargo build --workspace passes. cargo test --workspace: 330 pass, 0 fail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 08:48:09 +01:00
db654deecc agent: engine slop pass — DSP, typed errors, regex parsing, tracing, audit fixes
External code review on 2026-05-12 rated the codebase 4/10 across audio DSP, error typing, JS injection, env-var safety, ALSA parsing, and async logging. This commit lands the prognosis-level fixes plus three audit follow-ups.

Audio/DSP:
- StreamingResampler/rubato confirmed in the live capture path
- regression test at 12 kHz (rms < 0.01, ~40 dB) catches naive decimation
- near-Nyquist test at 9 kHz (rms < 0.05, ~26 dB) exercises transition band

Core errors:
- Other(String) removed; ProviderNotRegistered introduced
- Io variant restructured as struct with kind/message/raw_os_error
- FileNotFound display quotes paths
- Configuration variant removed (unused)

Core types:
- ModelId, EngineName backed by Cow<'static, str>; const borrowed ctor
- Megabytes::from_gb takes u64 (was f64)
- AudioSamples::sample_rate is NonZeroU32; zero-rate defensive branch removed

Capture:
- /proc/asound/cards parsing rewritten as anchored regex (OnceLock)
- regression test covers product names with embedded colons
- monitor_pattern_detection test restored alongside the regex test
- DEAD_SILENCE_FLOOR promoted to module-level with rationale
- DEVICE_VALIDATION_MS, SILENCE_RMS_FLOOR documented with field-observation rationale
- RMS validation loop made idiomatic
- eprintln! migrated to tracing with structured fields and targets

Tauri startup:
- unsafe std::env::set_var removed; ensure_x11_on_wayland renamed to warn_if_x11_env_unset_on_wayland (launcher/wrapper owns env-var contract)
- DB init + log prune + preferences load collapsed to one block_on
- build_preferences_script rewrites JS injection from JSON.parse string to direct object literal plus malformed-JSON guard and unit tests
- WebKitGTK microphone auto-grant logs warning at startup
- tracing subscriber initialised at top of run() (warn,magnotia=info,... on stderr; honors RUST_LOG); previously eprintln→tracing migration was silent because no subscriber existed

Filename counter:
- RECORDING_COUNTER uses SeqCst

Tests: cargo test --workspace --lib green (322 passed, 0 failed across 10 crates).

Three independent audits (original cleanup → Wren → fresh Codex subagent) concur on no critical findings.

Deferred to docs/superpowers/plans/2026-05-12-engine-slop-residuals.md: storage-layer typed errors, remaining eprintln→tracing sweep, capture actor-model refactor, property-based DSP testing, frontend/backend error boundary cleanup.
2026-05-12 22:03:58 +01:00
Claude
89c63891fa chore: rebrand from Kon/Corbie to Magnotia
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.
2026-04-30 13:06:55 +00:00
Claude
a7fdc96e7b fix(audio): log dropped capture errors instead of silently discarding
The cpal stream-error closure used `let _ = err_tx.try_send(...)` against a
bounded sync_channel(16). If the live session's listener stalled or the
frontend disconnected, runtime stream errors were silently dropped — the
diagnostic bundle showed nothing for a session that mysteriously stopped
working.

- Bump the error channel capacity 16 → 32 (matches AUDIO_CHANNEL_CAPACITY).
- On try_send failure, log to stderr with the device name + a per-session
  drop counter so the symptom is visible in the diagnostic bundle even
  when the typed event never reached the frontend.
- Plumb a new `dropped_errors: Arc<AtomicU64>` through `build_input_stream`
  alongside the existing `dropped_chunks`, mirroring the same pattern.

(kon-audio doesn't build in the audit sandbox: it links against ALSA
which the sandbox lacks. CI cross-platform compiles it.)

https://claude.ai/code/session_0189xUb6ie6t9qHkzatGZ9Rb
2026-04-25 09:37:51 +00:00
4700668df1 docs(readme): refresh test count 136 -> 245
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
2026-04-24 09:53:26 +01:00
fe61661305 chore(lint): clean up clippy warnings across workspace
Auto-applied cargo clippy --fix across 11 files — needless return,
unnecessary cast, map_or simplification, repeat().take() → repeat_n(),
iter().any() → contains(), manual char comparison, lifetime elision,
push_str single-char, reference immediately dereferenced.

Also fixed three lints on file_storage.rs manually: two doc-list-item
overindentations, plus the same needless-return. Baseline main was
not clippy-clean with -D warnings before; after this pass one
needless_range_loop warning remains (live.rs:1089) that clippy's
suggested rewrite would make less readable — left for a dedicated
refactor session.

Build + workspace tests remain green (245 passing, 0 failing, 1
ignored).
2026-04-24 09:43:56 +01:00
34fce3cf9e feat: OpenWhispr-inspired transcription polish pass
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
Major quality pass on top of Phase 2. Five substantive changes plus
cross-cutting touches across audio, hotkey, transcription, and Tauri
command layers.

  Transcription quality

  - Long-audio chunking in commands/transcription.rs: Parakeet and large
    file transcription now chunk-and-recompose with overlap trimming, so
    the live-path chunking advantage extends to file-based workflows.
  - Stateful live speech gate in commands/live.rs on top of the earlier
    duplicate-boundary filtering — distinguishes start-of-speech from
    mid-speech and holds state across chunks.

  Auto-learning corrections

  - New crates/ai-formatting/src/correction_learning.rs: extracts user
    text corrections from viewer edits and proposes additions to the
    active profile's vocabulary.
  - src-tauri/src/commands/profiles.rs bridge for frontend-driven
    confirmation of learned terms.
  - src/routes/viewer/+page.svelte hooks the learning path into the
    segment-edit flow so corrections feed profile_terms without a
    separate 'train this profile' UX.

  Transcript profile provenance

  - Migration v8 (crates/storage/src/migrations.rs) adds profile_id to
    transcripts, defaulting to DEFAULT_PROFILE_ID so existing rows stay
    valid.
  - crates/storage/src/database.rs: TranscriptRow + CRUD carry profile_id.
  - src-tauri/src/commands/transcripts.rs: add_transcript accepts and
    persists profile_id.
  - DictationPage.svelte + FilesPage.svelte send activeProfileId on
    capture so learned corrections are attributed to the right profile.

  Cleanup prompt contract

  - crates/ai-formatting/src/llm_client.rs hardened: the CLEANUP_PROMPT
    now specifies concrete do/do-not rules, ready for a real model-backed
    cleanup pass. The llm_client is still a stub — kon-llm remains unwired
    — but the prompt shape is final.

  Cross-cutting polish

  - Minor touches in audio (capture/decode/resample), hotkey (lib/linux/stub),
    core, transcription (concurrency/model_manager/local_engine/whisper_rs),
    and the rest of src-tauri/src/commands/*: error-path tightening, log
    clarity, TS-migration follow-ups (@ts-nocheck additions for incremental
    typing).

Verified locally: npm run check, cargo test -p kon-ai-formatting,
cargo test -p kon-storage, cargo test -p kon --lib commands::live::tests,
cargo check — all green.

Scope boundary: kon-llm crate is still a stub; task extraction remains
rule-based. Bundled local-LLM runtime is the next clean step and is not
in this commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 22:39:08 +01:00
6605266587 feat(ai-formatting): collapse adjacent repetitions in Clean/Smart modes + chore(audio): swap deprecated cpal .name() for description-based helper
ai-formatting:
  - rule_based.rs: collapse_repetitions() merges adjacent duplicate
    tokens like 'I I can' -> 'I can' and 'think think that' -> 'think
    that'. Normalises case and punctuation before comparison.
  - pipeline.rs: post_process now calls collapse_repetitions when
    format_mode is Clean or Smart. Added unit coverage.

audio:
  - capture.rs: replace the seven deprecated cpal DeviceTrait::name()
    call sites with a device_display_name() helper that uses the
    non-deprecated description() path. Keeps identical behaviour,
    silences compile warnings, ready for cpal upgrade.

Addresses the 'Christ. Christ.' live-transcription boundary duplicate
Jake saw during Group 1 dogfooding. Does not fix all cross-chunk
overlap cases (see live.rs OVERLAP_SAMPLES for the root cause) but
catches the common stutter pattern at post-processing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:05:36 +01:00
ea48d03cee agent: dogfood polish 2026/04/19 — Linux native chrome + History redesign + mic picker cleanup
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
Second dogfood sprint. Headline fix: Linux now uses native KWin/Mutter
decorations instead of fragile frameless `startResizeDragging`, which
collapsed diagonal corner resize to a single axis and made drag feel
laggy. macOS / Windows keep custom chrome via `useCustomChrome` gate.

Other changes:

- Cross-window preferences sync via `kon:preferences-changed` Tauri
  event — theme and font changes propagate live to float/viewer.
- Hotkey recorder rewritten to use capture-phase document listener
  gated by $effect; button focus was unreliable in webkit2gtk.
- History page redesigned for cognitive-load hygiene: title-first
  compact row, inline title input, Edit popout opening /viewer in
  edit mode, clipboard export as .md with YAML frontmatter, manual
  tag chips + + Add tag input, header tag filter (cap 7), global
  Starred filter, `tag:xyz` search syntax.
- `deriveAutoTags` kept as empty hook for post-Task-7 LLM topic tags;
  research found all previous auto-tag chips redundant with row UI.
- Viewer window adds edit mode with debounced-save textarea; native
  title renamed to "Kon - Transcription Editor".
- Window minimums updated per GNOME HIG + WCAG reflow research:
  main 960x600, float 360x480, editor 560x520.
- Microphone picker filters raw ALSA strings (hw:, plughw:, front:,
  sysdefault:, null) and dedupes by CARD=X. New `description` field
  on DeviceInfo reads /proc/asound/cards so Blue Yeti shows as "Blue
  Microphones" instead of the short "Microphones" card name.
- GPU reporting fixed: get_runtime_capabilities now returns
  accelerators=[cpu,vulkan] and whisper.supports_gpu=true, matching
  the transcribe-rs whisper-vulkan feature linked unconditionally.
- ResizeHandles kept for macOS/Windows frameless: 12px edges, 20px
  corners via CSS vars, pointerdown + setPointerCapture, corners
  above edges in z-order, rendered as sibling (not child) of the
  animated layout root so `position: fixed` is viewport-relative.
- Dueling drag-region handlers removed — `data-tauri-drag-region` and
  manual `startDragging()` were stacked on the same elements; kept
  the manual handler which has the button/input early-return logic.

See HANDOVER.md for the full session log and deferred items.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 14:30:42 +01:00
19a6b83cb2 audio: Day 2 — Codex follow-up hardening (channel disconnect, spawn_blocking, fallback silence guard, requeue counting, runtime error propagation)
Closes the 6 Codex review findings on the Day 1 mic-capture work
(commits 96980c7 + 41db162). Detail in
output/reports/kon-codex-mic-capture-followup-2026-04-17.md (CORBEL
workspace).

src-tauri/src/commands/audio.rs:
- D1: Sending an explicit stop signal before dropping stop_tx, so the
  accumulator task wakes up immediately rather than waiting for the
  Disconnected detection added below.
- D2: Wrapping MicrophoneCapture::start() in tokio::task::spawn_blocking.
  start() can spend up to 350ms × N_devices × 2 passes; running it on
  the async runtime froze other Tauri commands.
- M3: Match on rx.try_recv() error variants. Empty -> sleep + continue.
  Disconnected -> exit accumulator task immediately. Previous behaviour
  was an infinite loop after the capture stream died.

crates/audio/src/capture.rs:
- D3: Added DEAD_SILENCE_FLOOR (1e-7) gate that applies even in the
  fallback pass. PulseAudio/PipeWire can stream zero-valued bytes from
  a borked device; that is worse than failing fast.
- M1: Validation requeue (`for chunk in collected { try_send }`) now
  counts drops in the same dropped_chunks counter.
- M2: New CaptureRuntimeError type. The cpal stream error callback now
  forwards errors via a separate sync_channel (capacity 16) that the
  live session can drain via take_error_rx() and surface as toasts.
  Re-exported from kon_audio crate root.

cargo check -p kon-audio passes clean.

NOT YET DONE (M4): JACK-specific monitor name patterns. Defers until
testing on a JACK host. Current is_monitor_name() may miss JACK
conventions.

Wiring the new error_rx into the live session and surfacing as toasts
lands with the Day 3 error-toast system commit.
2026-04-17 13:02:51 +01:00
96980c7d5c audio: fix mic capture — skip monitor sources, validate by RMS, add device picker
Day 1 of the upgrade plan (output/reports/kon-upgrade-plan-2026-04-17.md
in the CORBEL workspace). Fixes the HANDOVER.md blocker: native live
transcription was capturing silence because PulseAudio/PipeWire monitor
sources (speaker loopback) were winning the device-selection race —
they deliver zero-valued bytes that satisfied the original
"any device that produces data within 350ms" check.

WHAT CHANGED:

crates/audio/src/capture.rs (rewrite):
- New `DeviceInfo` struct (serde-derived) for the Settings device picker
- New `MicrophoneCapture::list_devices()` enumerates inputs with metadata
- New `MicrophoneCapture::start_with_device(name)` for explicit selection
- Refactored `start()` with monitor-source filtering by name pattern
  (.monitor suffix, "Monitor of " prefix, "loopback" substring) and
  RMS-energy validation in a 350ms window
- Two-pass selection: real inputs first, monitor sources only as
  last-resort fallback with explicit warning log
- Drop counter (Arc<AtomicU64>) tracks chunks dropped by `try_send`
  failure under load — Codex review caught this as a silent-failure risk
- `dropped_chunks()` accessor for the live session
- Verbose tracing at every step for diagnosis
- Unit test for monitor-name detection
- `cargo check -p kon-audio` passes clean

crates/audio/src/lib.rs:
- Re-export `DeviceInfo`

crates/audio/Cargo.toml:
- Add serde dependency (for DeviceInfo derives)

src-tauri/src/commands/audio.rs:
- New `list_audio_devices` Tauri command (returns Vec<DeviceInfo>)

src-tauri/src/lib.rs:
- Register `list_audio_devices` in invoke_handler

src/lib/pages/SettingsPage.svelte:
- New "Audio" section with microphone picker dropdown
- Auto-populates on mount via `list_audio_devices`
- Refresh button + clear messaging about monitor sources
- Likely-monitor entries marked disabled in the dropdown
- Auto mode is the default (empty string in settings.microphoneDevice)

src/lib/stores/page.svelte.js:
- New `microphoneDevice` field in defaults (empty = auto-select)

NEXT STEPS (per the upgrade plan):
- Wire `microphoneDevice` from settings into `MicrophoneCapture::start_with_device`
  in the live and standalone capture paths (currently both still call
  the auto-selecting `start()`)
- Test on real hardware (Wayland + multiple input devices)
- Codex sanity-check of this diff is running in parallel; addendum to
  follow if anything substantive comes back

Refs: /home/jake/Documents/CORBEL-Projects/kon/HANDOVER.md
      output/reports/kon-upgrade-plan-2026-04-17.md (CORBEL workspace)
2026-04-17 12:43:13 +01:00
jake
a30c9cc107 feat(kon): add audio crate — cpal capture, VAD, rubato resample, symphonia decode
- File decode via symphonia (mp3, aac, flac, wav, ogg) with mono mixdown
- Sinc interpolation resampling via rubato 0.15 (48kHz/44.1kHz → 16kHz)
- WAV I/O via hound (read/write with f32→i16 conversion)
- Microphone capture via cpal 0.17 (WASAPI on Windows) with mpsc channel output
- Voice activity detection via Silero VAD V5 (voice_activity_detector 0.2)
- Async decode_and_resample() for file transcription pipeline
- 3 tests passing (resample passthrough, duration preservation, WAV roundtrip)
- clippy clean, no ort version conflicts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 20:56:30 +00:00