Commit Graph

16 Commits

Author SHA1 Message Date
3770815fbf agent: lumotia — v0.1 release-completion run
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
Closes the code-side v0.1 ship gate. All quality gates green:
cargo fmt/clippy/test (~327 tests), npm check (0/0), vitest 13/13,
scripts/dogfood-rebrand-drill.sh 8/8.

Phase F — first-run onboarding promoted to v0.1
- FirstRunPage with skip-to-main + failure recovery + event recording
- Six onboarding commands (record/list/has-completed + lumotia_events)
- Storage migration v17 (onboarding_events + lumotia_events tables)

UI hardening (in-scope items from v0.1-ui-hardening.md)
- StatusPill + PostCaptureCard components, 21st preview entry
- Sidebar recording-as-sacred-state (opacity + aria-disabled, reduced-motion)
- Settings 6-section regroup + Help section + Activation log + Privacy toggle
- Error-state copy sweep (DictationPage + SettingsPage, plain-language)
- Global :focus-visible rule, textarea outlines restored
- Ctrl+K / Ctrl+, / Escape bindings in +layout

LLM resilience
- rule_based_extract_tasks (regex-free imperative-verb extractor) +
  extract_tasks_with_fallback wrapper — task extraction never returns zero
- tokio::time::timeout(120s) wraps cleanup/tags/tasks commands

Release artefacts
- LICENSE (canonical AGPL-3.0), CHANGELOG (Keep-a-Changelog format)
- v0.1-release-notes, privacy-and-ai-use, install-warnings,
  tester-onboarding-kit, tester-acceptance-runbook, code-signing-setup,
  apple-silicon-rb08-runbook, virtual-audio-setup, v0.1-contrast-audit
- Workspace versioning + AGPL spdx; npm exact-pin (10 ranges removed)
- AppImage SHA-256 sidecar in build.yml
- README v0.1 section + Reporting-issues; canonical repo slug

Closure pass — items moved from human-required to code-complete
- KI-02 Linux idle inhibit: zbus 5 → org.freedesktop.login1.Manager.Inhibit
- KI-03 Windows sleep prevention: SetThreadExecutionState(ES_CONTINUOUS|...)
- acquire/release_idle_inhibit Tauri commands, wired in DictationPage
- Diagnostic-bundle frontend wire-up (Settings → Help button)
- WCAG-AA contrast fix via .btn-filled-text utility (no token changes)
- 8 destructive-action sites wrapped in plain-language confirm() guards
- KNOWN-ISSUES.md + v0.1-known-limitations.md updated (KI-02/03 fixed)

Scripts
- pre-tag-verify.sh, tag-day.sh, smoke-linux + driver
- parse-diagnostic-bundle.sh, parse-activation-log.py

Per-item audit trail: docs/release/v0.1-completion-status.md
Remaining: W-01…W-08 (signing certs, hardware probes, smoke matrix,
tester recruitment) — see docs/release/v0.1-known-limitations.md.
2026-05-15 06:59:08 +01:00
643985d2a8 agent: lumotia — Phase B.2 fix misleading "force-abort" doc + test name on supervisor shutdown
Phase B.2 audit of commit 1068ad9 (hotkey supervisor rearchitecture —
Race-1, Race-2, TOCTOU). The production behaviour is correct and the
integration tests in crates/hotkey/tests/listener_lifecycle.rs cover
Race-1 (per-device listener sender-clone drop on stop) and Race-2
(forwarder join on reconfigure) at the public-API level. The TOCTOU
window is closed by construction (insert-before-spawn under one mutex
hold) and the original author's // TODO(test): note at linux.rs:576
explicitly explains why a deterministic test would require faking
evdev::Device::open, which the crate doesn't expose — honoured.

One real residual: two satellite places in supervisor.rs claim that a
stuck task is "force-aborted" after SHUTDOWN_TIMEOUT, but the code does
NOT abort. `tokio::time::timeout(d, handle).await` consumes the
JoinHandle by value; when the timeout fires, the inner future (the
JoinHandle) is dropped, and dropping a JoinHandle DETACHES the task
rather than aborting it. The shutdown() doc-comment and the warn-log
message both correctly say "detached", but:

  * The SHUTDOWN_TIMEOUT const doc-comment said "we give up and abort
    it ... force-aborted with a warning".
  * The test name was shutdown_force_aborts_stuck_tasks_after_timeout.

A future maintainer trusting either of these would either insert
handle.abort() to make the implementation match (changing shutdown
semantics — abort skips cooperative cleanup) or conclude the doc was
wrong and need to retrace which is authoritative. Same B.1-class hazard
(comment claims one ordering, code does another).

Fix is doc + test-name only:
  * SHUTDOWN_TIMEOUT doc-comment now spells out detach-not-abort with
    the technical reason.
  * Test renamed to shutdown_does_not_block_on_stuck_tasks_after_timeout
    with a doc-comment clarifying that the elapsed-bounded assertion is
    what guards against a regression that reintroduces an unbounded
    handle.await — and that detach behaviour itself cannot be asserted
    from the test because register() moves the handle.

No production behaviour change; semantics already correct.

Verification:
  * cargo test -p lumotia-hotkey --lib --tests
      → 6 unit + 2 integration = 8/8 pass (unchanged).
  * cargo fmt --check → clean.
  * cargo clippy -p lumotia-hotkey --all-targets -- -D warnings → clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 19:19:52 +01:00
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
1068ad9c7d agent: code-atomiser-fix — hotkey supervisor rearchitecture (Race-1, Race-2, TOCTOU)
Fixes three interlocking concurrency leaks in the evdev hotkey listener
flagged by the atomiser full-sweep. Every spawned task is now owned by a
SupervisorHandle that broadcasts cooperative shutdown and joins every
JoinHandle with a 2s per-task timeout on stop(). Per-device attachment is
now insert-before-spawn under one mutex hold, closing the TOCTOU window.
The Tauri command layer now stores the forwarder JoinHandle alongside
the listener so reconfigures join it cleanly instead of leaking one
permanent forwarder per hotkey change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 15:21:50 +01:00
26c7307607 agent: lumotia-rebrand — docs, scripts, root config, residuals
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 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>
2026-05-13 12:38:03 +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
48c483894b agent: finish tracing migration for hotkey logs
Follow-up to 184214b. The eprintln→tracing sweep surfaced 6 existing
log::* calls in the hotkey crate that were silent at runtime — the
workspace builds tracing-subscriber without the tracing-log feature, so
log:: events never reached the tracing pipeline.

Migrating direct rather than adding a LogTracer bridge: the repo is
already standardising on tracing, the bridge adds a second logger init
path with "already initialised" edge cases, and the bridge would
indiscriminately route all log records (including future third-party
chatter), not just these known sites.

Migrated (6 sites, 2 files):
- crates/hotkey/src/linux.rs (5) — read /dev/input error, device open
  debug, device-attached info, device-listener-ended warn, event-channel-
  closed warn
- crates/hotkey/src/stub.rs (1) — non-Linux no-op info

Also removed the now-unused log = "0.4" dependency from
crates/hotkey/Cargo.toml. magnotia_hotkey=info filter target was
already added to init_tracing in 184214b, so these events emit at the
default level immediately.

Verification:
- cargo fmt --all -- --check
- cargo check -p magnotia-hotkey — clean
- cargo check -p magnotia — clean
- rg 'log::|eprintln!' crates/hotkey/src/ src-tauri/src/commands/ crates/ai-formatting/src/ — zero hits

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 22:34:26 +01:00
184214b60a agent: engine slop residuals B — eprintln → tracing sweep
Replaces 22 production eprintln! sites with structured tracing events
across 8 files. Closes Area B of the post-prognosis residuals plan
(docs/superpowers/plans/2026-05-12-engine-slop-residuals.md).

Files touched (22 sites):
- crates/hotkey/src/linux.rs (2) — hotplug watcher degraded-mode warnings
- crates/ai-formatting/src/pipeline.rs (1) — LLM cleanup fallback warning
- src-tauri/src/commands/transcription.rs (1) — chunking dispatch info
- src-tauri/src/commands/diagnostics.rs (1) — crashes-dir setup warning
- src-tauri/src/commands/tasks.rs (1) — malformed feedback row warning
- src-tauri/src/commands/power.rs (3) — App Nap acquire/release/fail
- src-tauri/src/commands/models.rs (5) — Whisper warmup lifecycle
- src-tauri/src/commands/live.rs (8) — session start, chunk dispatch,
  per-chunk delivery, inference errors, worker disconnects, listener
  loss, status-channel cascade

Levels: error for unrecoverable failures (inference disconnect, panic,
status cascade), warn for recoverable degradation (LLM fallback,
malformed rows, App Nap fail, hotplug watcher fail), info for lifecycle
(session start, chunk processed, App Nap acquire/release, warmup
complete, chunking dispatch), debug for per-chunk noise (speech-gate
skip, chunk dispatch).

Two new dependencies and two new filter targets:
- tracing = "0.1" added to crates/hotkey and crates/ai-formatting
- Default EnvFilter in src-tauri/src/lib.rs::init_tracing extended with
  magnotia_hotkey=info,magnotia_ai_formatting=info so the new targets
  emit at the default level

Out of scope (intentional, left as-is):
- crates/mcp/src/main.rs — CLI binary, stderr is the log contract
  (module docstring) so the JSON-RPC stdout stream stays clean
- crates/*/tests/*.rs and crates/core/examples/tuning_log_demo.rs —
  test/example diagnostic output relies on --nocapture stdio semantics

Discovery during sweep (not fixed — separate follow-up): hotkey crate
has 6 existing log:: calls (log::error/warn/info/debug) but the
workspace builds tracing-subscriber without the tracing-log feature, so
those events are currently silent. Worth a follow-up to either add the
tracing-log bridge or migrate hotkey's existing log:: calls to
tracing::.

Verification:
- cargo fmt --all
- cargo check --workspace --all-targets — clean
- cargo test --workspace — 330+ tests, zero failures
- rg eprintln! src-tauri/src/commands/ crates/hotkey/src/ crates/ai-formatting/src/ — zero hits

Pre-existing working-tree churn in crates/llm/, src/lib/pages/,
src/lib/utils/saveMarkdown.ts and the untracked phase10a dogfood notes
deliberately left unstaged per Jake's instruction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 22:27:06 +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
d5d751c9ad fix(hotkey): exit listener cleanly when event channel is dropped
The evdev listener's run loop did `let _ = event_tx.send(event).await`
inside the trigger-key match arm. If the receiver was dropped without
the explicit shutdown signal (set hotkey to None), the send returned
Err and the loop kept polling — sending into a closed channel forever
until something else terminated the task.

Replace with explicit handling: on Err, log via log::warn! once and
return Ok(()) from `run`. The shutdown-via-None path is unaffected.
kon-hotkey still 4/4.

https://claude.ai/code/session_0189xUb6ie6t9qHkzatGZ9Rb
2026-04-25 09:38:03 +00: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
9b0067b4c0 Land release blocker fixes and workspace 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
2026-04-23 00:16:09 +01:00
528facfab0 fix(rb-12): hotkey device filter consults configured HotkeyCombo
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>
2026-04-22 10:18:54 +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
Claude
ebf449b47b qa: restore boot, wire dead error rx, harden storage and config
Front-to-back QC pass turned up two independent missing-module
showstoppers (workspace did not compile; frontend did not load) plus a
handful of HANDOVER-claimed features that were wired but dead. Fixes:

P0 — gets the app booting again:
  - Add the never-committed src/lib/utils/runtime.js (hasTauriRuntime
    detection); 5 imports were resolving to nothing.
  - Add the never-committed crates/audio/src/streaming_resample.rs
    (rubato-backed StreamingResampler with new/push_samples/flush);
    declared in lib.rs and used 3x by live.rs but had no impl.
  - Drop the duplicate hasTauriRuntime import in routes/+layout.svelte.
  - Allow the transcript-viewer window to use the default capability
    (was missing from capabilities/default.json:windows, so the viewer
    window could open but not invoke any Tauri command).

P1 — features documented as working but actually dead:
  - Pump MicrophoneCapture::take_error_rx() into LiveStatusMessage::
    Warning each loop iteration in commands/live.rs. The HANDOVER
    promised cpal stream errors would surface as toasts; the channel
    was created and never read.
  - Replace .expect() on the WebKit media-permission setup with a
    logged warning. Failure no longer aborts the whole process.
  - Toast on save_preferences failure (preferences.svelte.js had a
    silent console.error — now warns once per failure run via the
    existing toasts store).

P2 — correctness/robustness:
  - add_dictionary_entry: switch INSERT OR IGNORE to ON CONFLICT
    DO UPDATE ... RETURNING id so duplicate terms get the real row id
    instead of a stale auto-increment.
  - search_transcripts: qualify ORDER BY fts.rank.
  - InsertTranscriptParams + TranscriptRow: bump sample_rate /
    audio_channels from i32 to i64 to match the Tauri DTO and avoid
    silent truncation at the boundary.
  - Drop the unused tauri-plugin-mcp dependency.
  - Promote sqlx in src-tauri/Cargo.toml from linux-only to
    unconditional (lib.rs names sqlx::SqlitePool unconditionally —
    macOS/Windows builds were latently broken).
  - hotkey/linux.rs: stop panicking the hotplug task on inotify
    failure; degrade to "no hotplug" with a stderr warning.
  - layout.svelte: store the global error/unhandledrejection handler
    refs and remove them in onDestroy so HMR/window teardown doesn't
    leak listeners.

Verified: cargo check -p kon-core -p kon-storage -p kon-cloud-providers
passes. cargo check on src-tauri/kon-audio/kon-hotkey requires alsa +
gtk system libs not present in this sandbox; their changes are
syntactically and type-checked against the rest of the workspace.
svelte-check requires npm install which is not available here.

https://claude.ai/code/session_018ozAs4UcRC8jbJbddqJtEw
2026-04-18 02:00:26 +00:00
8e70cf9ff9 agent: wayland — evdev hotkey backend, download resume, SHA256 integrity
Add kon-hotkey crate with evdev-based global hotkey capture that works on
Wayland (and X11). Patterns from whisper-overlay: per-device async listeners,
inotify hotplug with udev permission retry, watch channel for live config
updates. Frontend detects Wayland at startup and selects evdev or
tauri-plugin-global-shortcut automatically.

Model downloads now support HTTP Range resume for interrupted downloads and
optional SHA256 integrity verification (incremental, no second pass).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 17:50:48 +01:00