Commit Graph
96 Commits
Author SHA1 Message Date
Jatin K MalikandGitHub ffec466d74 docs: align README with live family status and on-device copy (#737)
Replace the 100% offline claims with on-device-after-model-download
language, mark Linux Available now, and add Phone and Gateway to the
family table with live sites and status.
2026-08-24 16:56:34 -07:00
Jatin K MalikandGitHub 0ac361db19 fix(copy): VocaWin is Beta, still unsigned (#733)
* fix(copy): VocaWin is Beta, still unsigned

Call VocaWin Beta on the site family card, About blurb, and README table, same word as VocaMac. Keep the unsigned / SmartScreen wording. No version tag.

* fix(copy): cite VocaWin v0.1.0-beta.1, no release URL

The git tag exists on VocaHQ/vocawin. GitHub Releases does not. About, README, and the site family card name the tag. Links stay on vocawin.com and the repo.
2026-08-24 11:41:17 -07:00
Sergey SilaevandGitHub 582d494633 chore(build): uv tooling, a Python 3.11 floor, and verified model downloads (epic #701, phases 2.5 & 5) (#713)
* chore(build): migrate justfile tooling to uv

All recipes now run through 'uv run' against .venv, with a shared
DEV_EXTRAS variable (dev + vad) because uv syncs the environment
exactly and would otherwise uninstall the dev tools between
recipes. 'deps' installs dev+vad; new 'deps-all' covers every
extra. 'build' switches to 'uv build'; 'version' uses --no-sync.

Bump [tool.uv] required-version to >=0.12,<0.13 for uv 0.12.x, and
raise the mypy python_version target to 3.12: mypy 1.19 in the lock
cannot target 3.9 and numpy 2.x stubs need a 3.12 target to parse
(mypy is not run in CI or pre-commit; this only affects 'just
typecheck').

* fix(tests): isolate test runs from real XDG state; fix Arch model-path crash

Local test runs failed en masse (185 failures) while CI stayed
green: tests picked up the developer's real ~/.local/share/vocalinux
models via the default XDG paths and switched IBus/keyboard code
paths through the desktop session env (XDG_CURRENT_DESKTOP/
XDG_SESSION_TYPE on GNOME/Wayland, issue #478 branches). conftest
now points XDG base dirs at a throwaway session-wide directory and
clears session variables at import time, mirroring a fresh CI
runner (paths like MODELS_DIR freeze at first import during
collection, so fixture-time isolation is too late).

Also guard the Arch branch of _get_system_model_paths(): it removed
/usr/local/share/vocalinux/models unconditionally and crashed with
ValueError on Arch hosts when a custom XDG_DATA_DIRS never added
that path. Add regression tests, and make the lock-file test assert
the actual $XDG_DATA_HOME/vocalinux contract instead of the
hardcoded ~/.local/share default.

* fix(tests): keep the IBus engine double a plain class

Python 3.14's unittest.mock re-instantiates a user subclass when it builds
child mocks (klass(name=...)). VocalinuxEngine inherits from whatever
IBus.Engine resolves to, and the test module bound that to the MagicMock
class itself, so every engine instantiation raised

    TypeError: VocalinuxEngine.__init__() got an unexpected keyword argument 'name'

on 3.14 while passing on 3.13. Replace it with a plain stand-in class that
still hands out per-instance MagicMocks for the IBus API surface the engine
touches.

The same pattern remains in test_ibus_engine.py, test_ibus_engine_utils.py,
test_ibus_active_engine_guard.py and test_ibus_xkb_wayland.py; those never
instantiate the engine, so they are unaffected for now.

* fix(install): build the venv from the system Python

install.sh looked up a bare `python3` from PATH. Started from an activated
virtualenv — a shell left in uv's .venv after `just deps` — it built venv/
from that interpreter, where distro PyGObject is invisible even with
--system-site-packages, and the run aborted with

    Distro PyGObject (python3-gi / python3-gobject) is not importable in the venv.

A mismatched venv/ then survived every retry, because the installer reuses
whatever venv it finds.

- drop an inherited VIRTUAL_ENV (and its bin from PATH) before any
  interpreter lookup
- select the interpreter explicitly: $SYSTEM_PYTHON (default
  /usr/bin/python3) or PATH python3, preferring one that can import gi,
  and create the venv with it instead of `python3`
- recreate venv/ when it was built by a different interpreter
- name the interpreter in the PyGObject guard's error

Documents the two environments (uv's .venv for tooling, venv/ for the
installed app) in CONTRIBUTING, the justfile header and AGENTS.md, and adds
the mismatch symptom to the INSTALL troubleshooting section.

* chore(python): raise the supported floor to 3.11

requires-python promised 3.9 while the CI matrix ran 3.9/3.10/3.11/3.13,
the classifiers advertised up to 3.14, mypy targeted 3.12 and install.sh
enforced 3.9 — five different answers to "which Python does this support".

Settle on 3.11 everywhere: pyproject (requires-python, classifiers, black
targets), install.sh's MIN_VERSION, check-system-deps.sh, the distro package
map, the CI matrix (now 3.11-3.14, matching the classifiers), the release and
nightly workflows, and the docs.

mypy now targets the floor instead of 3.12, so type checking covers what we
promise; numpy 2.x ships stubs in 3.12 syntax that a 3.11 target cannot
parse, so its imports are skipped. (mypy has 71 pre-existing errors either
way; no CI job gates on it.)

uv.lock and the requirements/* exports are regenerated — dropping 3.9/3.10
removes most of the version-conditional resolution branches.

tests/test_python_version_policy.py pins the invariant: install.sh's floor,
requires-python, the classifiers and the CI matrix must agree.

* ci: run lint and tests from uv.lock

The lock file and the hash-pinned exports were not enforced anywhere: CI
still built a venv by hand and installed unpinned `PyGObject` plus
`-e ".[dev,vad]"`, so the tool versions it checked against had nothing to do
with the ones `just lint` uses locally.

Both Python jobs now use astral-sh/setup-uv and run through `uv sync
--locked` / `uv run --locked`, which also fails the build when uv.lock drifts
from pyproject.toml.

Partially covers phase 5 of #701 (tests install from the lock, lock freshness
gate); trusted publishing, artifact checksums and action SHA pinning are
still open there.

* ci: lint from a dedicated dependency group

The lint job failed on this branch: `uv run --extra dev` syncs the whole
project, so it tried to build pyaudio from source on a runner that installs
no system dependencies.

    src/pyaudio/device_api.c:9:10: fatal error: portaudio.h: No such file or directory

Move black/isort/flake8 out of the `dev` extra into a `lint` dependency
group. CI runs `uv run --locked --only-group lint`, which installs the three
pure-Python tools and skips the project entirely — no portaudio or
girepository headers needed. `just deps` and DEV_EXTRAS request the group
alongside the dev extras, so the local environment still carries test and
lint tooling at once and `just lint` matches CI version for version.

pre-commit is unaffected: its hooks pin their own tool versions upstream.

* fix(install): never configure an engine the venv cannot import

vosk became an optional extra in #705, but the installer still writes
`"engine": "vosk"` into config.json on the whisper.cpp fallback path even
when installing the extra only produced a warning. config.json also survives
reinstalls — every writer guards on "file does not exist" — so an engine
picked by an earlier attempt outlives the venv that supported it. Either way
Vocalinux dies at startup:

    ModuleNotFoundError: No module named 'vosk'

- the fallback now writes the vosk config only when `import vosk` actually
  succeeds, and otherwise leaves the engine configuration alone
- a new verify_configured_engine() runs near the end of the install: if
  config.json selects vosk and the venv cannot import it, it says so and
  prints both fixes instead of leaving a broken install behind

* feat(models): verify every model download against a pinned digest

Pins a sha256/md5 per downloadable speech model in
src/vocalinux/utils/model_checksums.txt and verifies against it in both
install.sh and the runtime downloaders, before the file is moved into place.
Verification fails closed. Covers phase 2.5 of #701; see the PR for details.

* docs(agents): rebase AGENTS.md onto the #727 rewrite

* fix(install): hash models that are already on disk instead of trusting them

* refactor(models): one download path per engine, and fix Whisper's

* docs(install): drop distros that cannot meet the 3.11 floor

* docs: retire the distros and Python versions the 3.11 floor rules out

* fix(install): abort instead of warning when Python is below the floor

* fix(install): fall back to the system Python, not the one on PATH

* fix(install): match an existing venv by installation, not by X.Y

* fix(install): repair a config naming an engine the venv cannot import

* fix(models): pin VOSK by the sha256 of bytes we fetched, not upstream's md5

* fix(justfile): request the dev set in every recipe that syncs

* test(version): scan the docs and website trees for a stale Python floor

* docs: correct the stale model-checksum and distro claims

* fix(models): stamp the VOSK tree the app extracts, as the installer does

* fix(install): replace an unverified VOSK model only once its successor is ready

* docs(install): align the Fedora floor with the rest of the tree

* test(install): drop an f-string with no placeholders

* test(models): stub the downloader probe the VOSK installer test relies on

* docs: drop the long dashes from two model-checksum comments

* fix(install): gate on the interpreter, not on the distro release label

* fix(justfile): export the lint group into requirements/dev.txt

* fix(models): unpack the VOSK tree into staging and stamp it before the swap

* fix(whisper): adopt a checkpoint an earlier release stored under the catalog name

* docs(settings): state what a stray Whisper copy really means for deletion

* fix(models): hash a whisper.cpp model found on disk before it reaches ctypes

* docs(contributing): stop telling readers to uninstall their linters

* fix(install): stop warning off distros the project documents as supported

* docs(distros): file the supported derivatives under supported
2026-08-24 00:25:06 -07:00
Jatin K MalikandGitHub ba9cca844b chore(release): prepare v0.16.0
Stable minor since v0.15.0. Bumps version to 0.16.0 across app, web, AUR, and Flatpak AppStream, and refreshes docs, changelog, and SECURITY.

Tag v0.16.0 after this lands on main.
2026-08-23 01:33:08 -07:00
Jatin K MalikandGitHub 8dc99a3b2c Point Discord and X community links at VocaHQ (#722)
Replace the old Discord invite, switch the X follow shield to @vocahq,
and add Discord to CONTRIBUTING and the site footer.
2026-08-20 19:38:37 -07:00
Sergey SilaevandGitHub 95d135ebbf chore(deps): lock dependencies with uv and pin every build input
Phases 0-1 of #701. Drops dead deps, moves vosk to an optional extra, adds uv.lock and hash-pinned requirements exports, pins pywhispercpp to 1.5.0.

Closes #705. Refs #701.
2026-08-18 16:26:13 -07:00
Jatin K MalikandGitHub 8e308a1735 fix(docs): rename VocaServer to VocaGateway; reuse GITHUB_REPO_URL (#697)
Point README/CONTRIBUTING sibling links at VocaHQ/vocagateway, and drive
homepage GitHub links and install/uninstall commands from GITHUB_REPO_URL.
2026-08-16 19:23:07 -07:00
Jatin K MalikandGitHub 32a17a9659 chore: point GitHub URLs at VocaHQ (#696)
Repo links, install one-liners, and release checks now use
github.com/VocaHQ/vocalinux. The site mentions VocaHQ without a redesign.

The Codeberg mirror, personal email, and X handle are unchanged.
2026-08-16 15:22:22 -07:00
Jatin K MalikandGitHub edca65d22e docs: add Discord and VocaHQ README shields (#695) 2026-08-16 13:44:40 -07:00
Jatin K MalikandGitHub ecd5839a13 feat(settings): delete unused downloaded speech models (#671)
* feat(settings): delete unused downloaded speech models

Add a Remove Model dropdown on the Speech Model page so whisper.cpp,
Whisper, and VOSK downloads can be deleted from Settings. The currently
selected model is marked in use and cannot be removed until you switch
away from it.

Fixes #650

* fix(settings): move unused model deletion below the picker

Unused downloads is its own group under the model info card. Only leftover
files appear, each with a Delete button. The group hides when empty.

* fix(settings): collapse unused downloads into an expander

Keep leftover models behind one row so a long list does not stretch the
Speech Model page. Expand to delete files one at a time; the list scrolls
once it grows past a few entries.

* fix(settings): keep leftover model list from clipping in the expander

Wrap the unused-downloads list so the expander can show a few rows and
scroll the rest, instead of painting only the first leftover.
2026-08-12 23:42:36 -07:00
Jatin K MalikandGitHub 068530535b chore(license): migrate from GPL-3.0 to AGPL-3.0 (#660)
Align Vocalinux with the other VocaHQ distribution projects
(VocaMac, VocaPhone, VocaServer) under AGPL-3.0.
2026-08-08 13:10:37 -07:00
Jatin K MalikandGitHub c337d8f56d feat(shortcuts): default to hold Right Alt (push-to-talk) for new installs (#648)
* feat(shortcuts): default to hold Right Alt push-to-talk on first install

Double-tap Ctrl conflicts with many desktop and app shortcuts, so new
installs now use hold Right Alt (Option) in push-to-talk mode. Existing
config.json values are preserved unchanged.

Updates README, user guide, AGENTS.md, first-run dialog, website copy,
and tests to match the new defaults.

* refactor(shortcuts): trim redundant default-change test and comments

Drop the fresh-install assertion that duplicated DEFAULT_CONFIG coverage,
remove the duplicated Right-Alt rationale from config_manager, and drop a
vacuous source-string check from the settings shortcuts test.

* fix(shortcuts): align install.sh seeds and preserve legacy toggle mode

install.sh still wrote ctrl+ctrl without mode, so merges with the new
push_to_talk default became hold-Ctrl. Seed right_alt + push_to_talk for
new installs, and migrate existing shortcut-only configs to mode=toggle
so prior behavior is unchanged.

* style(config): fix black formatting after shortcuts migration

* fix(shortcuts): preserve legacy defaults when shortcuts section is missing

Existing config files without a shortcuts section previously inherited
ctrl+ctrl toggle from DEFAULT_CONFIG. Pin those historical defaults on
upgrade so the new first-install Right Alt push-to-talk defaults do not
silently change behavior.

* docs(agents): unwrap hard-broken dictation control paragraph

Keep the AGENTS.md paragraph as a single line like the surrounding prose.
2026-08-08 00:07:54 -07:00
Jatin K MalikandGitHub 5eff933d73 Update task list in README
Updated README to reflect completed tasks and removed outdated items.
2026-08-02 23:50:23 -07:00
Jatin K MalikandGitHub a320801d30 docs(web): refresh screenshots for v0.15 (light/dark) (#630)
* docs(web): refresh screenshots for v0.15 sidebar settings UI

Recapture product and settings gallery shots against the searchable
sidebar settings dialog, keeping the previous asset filenames and
exact pixel dimensions with wallpaper padding around each window.

* fix(web): correct screenshot semantics after adversarial review

Keep the existing transcription and tray images because the replacements did not
show their claimed flows. Populate the Logs dialog and unlock Advanced settings
so those refreshed images demonstrate the features described by the gallery.

* fix(web): retake screenshots as square crops with uniform padding

Resize settings dialogs to a near 1:1 window, capture with ~28px wallpaper
padding on all sides, open About from the tray menu, and skip redoing the
awkward XFCE system-tray asset.

* docs(web): retake v0.15 screenshots on GNOME (light/dark)

Window-only captures from Ubuntu/GNOME at 960x720 for settings and
logs, with matching dark variants under screenshots/dark/. Replace the
old Shortcuts shot with Performance to match the sidebar.

* feat(web): theme-aware light/dark screenshot switching

Serve paired GNOME captures and swap them with the site theme via
dark:hidden / hidden dark:block. Replace Shortcuts gallery entry with
Performance to match the v0.15 sidebar.

* docs(web): refresh screenshots after About moves into Settings

Rebase onto main brought the in-app update checker: About is now a
sidebar settings page. Recapture light/dark GNOME panels at 960x720 and
update gallery copy/metadata accordingly.

* docs: use single screenshot source for README and website

Point README images at web/public/screenshots so product shots live in
one place, drop the unused resources/screenshots tree (including the old
demo video and about-updates set), and replace the missing shortcuts
shot with performance.

* docs(web): refresh light/dark screenshots and product grid

Replace the screenshot set with fresh captures for both themes, and
lay out the three Product shots in a single equal-height row.

* fix(web): align screenshot metadata, sizes, and theme loading

Restore dictation copy for the 00-transcription asset, set width/height
from the recaptured PNGs, preload only the light next/image twin when
priority is set, and eager-load both theme variants by default so dark
mode does not flash empty on first toggle.

* fix(web): show full settings screenshot without crop

Use object-contain so the homepage settings dialog fits the frame
instead of object-cover clipping the sidebar.
2026-08-02 23:48:17 -07:00
Jatin K MalikandGitHub 27eb1d3807 feat(settings): in-app update checker with stable/nightly channels (#631)
* feat(settings): add in-app update checker with stable/nightly channels

Move About into the Settings sidebar and check GitHub Releases for updates.
Stable uses /releases/latest; Nightly follows nightly-YYYY-MM-DD tags.
Remove the standalone About dialog and wire tray About to Settings.

Fixes #183

* docs(readme): update About screenshot caption for Settings page

* fix(settings): address update-checker review and About polish

Discard stale in-flight results when the update channel changes, page
through GitHub releases for nightly tags, restore the About logo next
to the title, and replace the em dash in the app description.

* docs(screenshots): add About update-checker state captures

Host PR review screenshots on the branch so GitHub can render them
from raw.githubusercontent.com (Cursor artifact URLs 403 in PR bodies).

* fix(updates): recognize .devYYYYMMDD nightlies and clear Open style

Parse CI nightly versions like 0.14.2.dev20260802+sha when checking for
updates, and drop the suggested-action style from Open after a failed
GitHub lookup.
2026-08-02 20:25:40 -07:00
fbb81238f5 chore(release): prepare v0.15.0 (#609)
* chore(release): prepare v0.15.0

Bump version across app, web, AUR, and Flatpak metainfo. Document GitHub
release-notes rules, refresh README/UPDATE/INSTALL/USER_GUIDE for the 0.15
series (sidebar settings, AppImage, auto-pause/keepalive, Vulkan device
selection), and align website product surfaces with shipped features.

Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>

* docs(release): fold latest main into v0.15.0 notes

Include dictation capitalization/trailing-space, ibus-wayland injection,
IBus teardown, and settings notice polish landed on main after the initial
release prep rebase.

Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>

* docs(release): include Bluetooth mic crash fix in v0.15.0 notes

Fold #599 (PortAudio Bluetooth SCO probe heap corruption) into README,
UPDATE, changelog, AppStream, and release history after rebasing onto main.

Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>

* docs(release): include language catalog expansion in v0.15.0 notes

Fold #616 (Hungarian and expanded speech languages, Fixes #565) into
README, UPDATE, changelog, AppStream, PRODUCT.md, and release history
after rebasing onto latest main.

Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>

* docs(release): fold settings footer and language follow-ups into v0.15.0

Include #618 sidebar dictation footer, #619 Custom Shortcut Record/Set
restore, and #617 English (India) Whisper language mapping after rebasing
onto latest main.

Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>
2026-08-02 15:26:03 -07:00
Jatin K MalikandGitHub 053fc173fa Adjust logo size and enhance README header
Updated logo size and improved header formatting.
2026-07-26 23:49:15 -07:00
Jatin K MalikandGitHub 070008344f Update README
Removed image of Vocalinux users and updated project description.
2026-07-26 23:47:51 -07:00
44dac3b4ab docs(mirror): add Codeberg mirror setup and optional sync workflow (#595)
* docs(mirror): add Codeberg mirror setup and optional sync workflow

Document one-time Codeberg migration (pull mirrors are disabled on
Codeberg.org) plus an optional GitHub Actions push for ongoing sync.

Links the expected mirror URL from README and CONTRIBUTING.

Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>

* docs(mirror): drop maintainer setup doc from PR

Keep only the README mirror table and optional sync workflow.
Setup notes are one-off and do not belong in the repo.

Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>

* chore(ci): remove obsolete mirror setup comment

Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>
2026-07-26 18:14:09 -07:00
Jatin K MalikandGitHub 830d24577a docs(readme): redistribute header badges into three rows (#545)
Four badge rows felt too tall above the hero. Collapse to three
rows (5 / 6 / 5) while keeping the narrow-to-wide step-out layout.
2026-07-17 19:35:30 -07:00
Jatin K MalikandGitHub d010a16eda docs(readme): pin CI badge to main and restyle social/coverage badges (#544)
* docs(readme): pin CI badge to main and restyle social/coverage badges

Scope the Vocalinux CI status badge to the main branch so PR failures no
longer flip the README shield. Restyle the X follow badge to black/white X
aesthetics, and set Codecov coverage.range so 80%+ coverage shows green.

* docs(readme): use static X follow badge without broken count

Shields.io no longer returns Twitter/X follower counts (empty right-side
value after API restrictions). Switch to a static black badge that shows
Follow @jatinkrmalik with the X logo instead of an empty dynamic count.
2026-07-17 19:09:04 -07:00
Jatin K MalikandGitHub 10b6f479a8 docs(readme): center-align header before hero image (#542)
* docs(readme): center-align header before hero image

Wrap icon, title, subtitle, and shields in a centered div so the top
of the README lines up cleanly above the hero image.

* docs(readme): tighten header badges and add social/install shields

Three clear rows: identity (Stable, release, license, PyPI, AUR),
quality (CI, Python, Linux, codecov), and community (stars, forks,
issues, contributions, X follow). Drop low-signal noise (watchers,
commit activity, last commit, Made with GTK). Slightly larger logo.

* docs(readme): add privacy, distro, and PRs-welcome shields

Expand the header into five scannable rows: identity, product values
(privacy/offline, data stays local, X11|Wayland, PRs welcome), official
distro logos linking to DISTRO_COMPATIBILITY, quality, and community.
Drop the generic Platform: Linux badge in favor of named distros.

* docs(readme): trim header to four badge rows

Drop Stable (release version is enough), merge privacy into one badge,
and remove stars/forks/issues (already on the GitHub repo page). Keep
X follow with CI/Python/codecov on the last row.

* docs(readme): order badge rows narrowest to widest

Step the header out toward the full-width hero: values → identity →
quality/social → distros as the base row.
2026-07-17 18:58:14 -07:00
Jatin K MalikandGitHub 3d65e5cea9 chore(release): prepare v0.14.2 (#537)
* chore(release): prepare v0.14.2

IBus stability patch on the 0.14 series: engine process launch after XDG
import (#534) and FocusIn gate for first dictation on GNOME Wayland (#533).

Keep 0.14 series feature list in README/UPDATE for patch releases; changelog
and AppStream note only the delta. Document that rule in RELEASE_PROCESS.

* fix(release): address 0.14.2 review findings

- Dates: v0.14.2 uses 2026-07-17 (not before 0.14.1)
- AUR: sha256sums=SKIP until tag; document updpkgsums in RELEASE_PROCESS
- Single version source: package __init__ re-exports version.py; User-Agent uses __version__
- Docs: drop redundant series recaps; shrink AppStream/changelog delta
- README ecosystem status: Stable v0.14.2 (not Beta)

* docs(release): include settings scroll fixes in 0.14.2 notes

Cover #538 and #541 (scrollable settings tabs / wheel polish) in README,
UPDATE, website changelog, AppStream, and version history after rebasing
onto main.
2026-07-17 18:42:53 -07:00
Jatin K MalikandGitHub 1783331c0d chore(release): prepare v0.14.1 (stable for Flathub) (#532)
Drop beta suffix so Flathub stable AppStream lint accepts the release.
2026-07-16 19:00:48 -07:00
Jatin K MalikandGitHub 853c1504b2 chore(release): prepare v0.14.1-beta (#525)
Patch release for Flatpak/AUR packaging and post-0.14.0 fixes:
installer wrappers, ydotool dual API and Flatpak socket probe, model
download timeouts, layout-aware hotkeys, and related docs/web bumps.
2026-07-16 17:51:45 -07:00
Jatin K MalikandGitHub 3deb523efd feat(flatpak): add Flatpak packaging for universal distribution (#484)
* feat(flatpak): add Flatpak packaging for universal distribution

Adds a Flathub-ready Flatpak for the whisper.cpp engine, plus the minimal
runtime adaptations Flatpak actually needs — deliberately scoped down from the
earlier attempts (#416, #428), which bundled unrelated whisper.cpp GPU, audio,
and clipboard changes.

Packaging (packaging/flatpak/):
- app manifest, AppStream metainfo, and desktop entry (com.vocalinux.Vocalinux)
- generated offline Python dependency modules (flatpak-pip-generator)
- bundled shared modules: PortAudio, libayatana-appindicator, xdotool, xsel

Runtime changes (Flatpak-only, behaviour unchanged outside a sandbox):
- utils/paths.py: honour XDG_CONFIG_HOME/XDG_DATA_HOME so config, models and
  runtime data live under ~/.var/app/<app-id> in the sandbox
- autostart uses `flatpak run <app-id>` (the host launcher is always on PATH)
- text injection and keyboard backend detect a Wayland host reached via XWayland
  (no Wayland socket granted) and route through xdotool / pynput-on-X11
- tray indicator references the exported `<app-id>-*` host icon theme names

Also: a CI workflow building x86_64 + aarch64 bundles, and README / packaging
README / distro-compatibility doc updates.

Verified with a full flatpak-builder build + bundle install on aarch64:
pywhispercpp loads its native libraries without LD_LIBRARY_PATH, XDG paths
redirect correctly, bundled tools are present, and the entrypoint runs.
Manifest and builddir lint are clean and AppStream metadata validates.

Closes #167

* chore(flatpak): sync metainfo version to 0.14.0-beta

Also ignore flatpak-build-dir/ so local builder output stays untracked.

* refactor(flatpak): trim docs and comments after ponytail review

Drop redundant packaging README command blocks, shrink path/tray/autostart
comments, and stop ignoring a non-canonical build-dir name.

* fix(flatpak): close readiness gaps for v0.14.0-beta

Route log files through XDG data dirs so Flatpak keeps them under
~/.var/app, refresh AppStream screenshots to vocalinux.com, and use
the SPDX GPL-3.0-only license id.

* fix(flatpak): enable global hotkeys via evdev and --device=input

pynput over XWayland only receives keys for the focused X client. Prefer
evdev inside Flatpak and grant /dev/input so shortcuts work app-wide.

* fix(flatpak): inject text with ydotool/uinput on Wayland

xdotool only reaches XWayland clients, so typing appeared to succeed but
never hit native apps. Ship ydotool, grant --device=all for uinput, start
ydotoold on demand, and type via uinput inside the Flatpak.

* fix(flatpak): paste via wl-copy + Ctrl+V instead of typing

ydotool type injects character-by-character. Ship wl-clipboard, grant
--socket=wayland, and prefer clipboard paste for instant insertion.

* test(text-injection): expect ydotool default key-delay of 2

Matches the shipped VOCALINUX_YDOTOOL_KEY_DELAY default used when
clipboard paste falls back to character typing.
2026-07-16 00:03:30 -07:00
Jatin K MalikandGitHub eba4801043 docs(screenshots): refresh v0.14 UI shots and add website gallery (#521)
* docs(screenshots): refresh v0.14 settings/About shots and add website gallery

Replace the outdated About dialog screenshot and supersede the old single
settings dialog with the six v0.14.0-beta settings tabs. Keep unique product
shots that have no replacements. Add a dedicated /screenshots/ website page
with header/nav discoverability and a homepage link (no full gallery on home).

* docs(screenshots): drop obsolete features-overview shot

The annotated features overview was the pre-tabbed settings panel and no
longer matches the v0.14 UI. Remove it from README, website gallery, and assets.

* docs(screenshots): ship full-resolution web transcription shot

Restore the original PNG instead of the downscaled copy so the website
gallery matches the repo assets bit-for-bit.

* feat(web): add click-to-expand lightbox on screenshots gallery

Open a full-screen dialog when a shot is clicked, with prev/next controls,
keyboard arrows, Escape to close, and captioned counter for browsing the set.

* fix(web): avoid next/image HMR crash on screenshots gallery

Use plain img tags in the client gallery so dev-mode webpack chunk
reloads do not throw options.factory call errors while hydrating.
2026-07-15 00:18:26 -07:00
Jatin K MalikandGitHub 6545e4ea66 feat(packaging): add AUR release package and CI publish (#518)
* feat(packaging): add AUR release package and CI publish

Ship packaging/aur/vocalinux for yay installs of tagged releases, wire
AUR publish into the release workflow (skipped until secrets are set),
and document one-time maintainer setup.

Fixes #116

* refactor(packaging): slim AUR PR to PKGBUILD + CI

Drop systemd unit, install script, website edits, and long docs.
Keep release PKGBUILD, minimal publish job, and short AUR setup notes.
2026-07-14 23:41:31 -07:00
Jatin K MalikandGitHub 2fd7e7a7b3 Update README.md 2026-07-14 00:53:57 -07:00
Jatin K MalikandGitHub c942e9dd4a Enhance README with Star History section
Added a responsive star history chart to the README.
2026-07-14 00:53:03 -07:00
Jatin K MalikandGitHub 8a085b5395 chore(release): prepare v0.14.0-beta
* chore(release): prepare v0.14.0-beta

- Bump version 0.13.0-beta -> 0.14.0-beta (src/vocalinux/version.py)
- README: refresh What's New for v0.14.0-beta and bump comparison table
- docs/UPDATE.md: add v0.14.0-beta section and bump checkout example
- SECURITY.md: mark 0.14.x supported, 0.13.x unsupported
- docs/RELEASE_PROCESS.md: add v0.14.0-beta to version history
- web: bump package.json / package-lock.json / page.tsx schema + badge
- web changelog: add v0.14.0-beta entry

* ci(codecov): allow 0.5% project coverage threshold

Prevents version-bump/docs-only PRs from being blocked by minor
coverage fluctuations (e.g. -0.04% on a release-prep branch).

* docs(release): correct chronological order in version history table

* docs(release): add #509 shortcut UI exclusivity fix to v0.14.0-beta notes
2026-07-13 23:44:07 -07:00
Jatin K MalikandGitHub 85927be4b4 feat(asr): FunASR/SenseVoice support for the Remote API engine (#468)
* feat(asr): add chat audio remote benchmarking

* style(asr): apply black formatting

* test(main): include remote API model kwarg

* test(asr): add coverage for chat-completions error handling and parsing

Add 10 new tests to cover uncovered lines in PR #468:
- ConnectionError handler in _try_chat_completions_audio_api (lines 1601-1602)
- _parse_chat_completion_transcription edge cases: None, list content,
  empty/whitespace strings, JSON without text field, plain text, and
  single-line language metadata (lines 1610, 1613-1621, 1625, 1629-1640)

Coverage for recognition_manager.py improved from 85% to 86%.

* feat(asr): support FunASR remote responses

* refactor(asr): scope remote FunASR support to the #469 path

Drop chat-completions/Qwen client, evaluation notes, and the remote ASR
benchmark harness. Keep model field, tolerant OpenAI response parsing,
SenseVoice label stripping, FunASR docs, and tests.
2026-07-13 15:03:19 -07:00
Jatin K MalikandGitHub 63c1053d8b chore(release): prepare v0.13.0-beta (#489)
- Bump version 0.12.0-beta -> 0.13.0-beta (src/vocalinux/version.py)
- README: refresh "What's New" for v0.13.0-beta and bump comparison table
- docs/UPDATE.md: add v0.13.0-beta section and bump checkout example
- SECURITY.md: mark 0.13.x supported, 0.12.x unsupported
- docs/RELEASE_PROCESS.md: add v0.13.0-beta to version history
- web: bump package.json / package-lock.json / page.tsx schema + badge
- web changelog: add v0.13.0-beta entry and refresh dateModified
2026-07-01 17:32:36 -07:00
Jatin K MalikandGitHub e0ac5e409c feat(whisper): add guided whisper.cpp model variants (#465)
* feat(whisper): refine whisper.cpp model selection

* refactor(whisper): exclude diarization model from picker

* docs(whisper): document guided model variants

* fix(ui): cap settings dialog height at 600px to prevent excessive height on high-res displays
2026-06-11 22:22:43 -07:00
Jatin K MalikandGitHub 748d318515 chore(release): prepare v0.12.0-beta (#459)
* chore(release): bump version to v0.12.0-beta

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

* docs(release): document v0.12.0-beta changes

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

* docs(security): update supported beta version

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

* chore(web): refresh v0.12.0-beta website metadata

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

* fix(web): type lazy syntax highlighter

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
2026-06-07 00:21:29 -07:00
Jatin K MalikandGitHub 78f377fd0f fix(models): correct download size metadata for whisper.cpp and VOSK (#453)
* fix(models): correct download size metadata for whisper.cpp and VOSK

The size_mb values in WHISPERCPP_MODEL_INFO were using parameter counts instead of actual download sizes, causing the UI to display incorrect sizes (e.g., showing 39 MB when actual download is 74 MB). Updated all whisper.cpp models with verified sizes from Hugging Face and adjusted VOSK medium/large sizes to better represent actual downloads.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

* docs: update model download sizes to match actual downloads

Update whisper.cpp size references from parameter counts to verified download sizes (e.g., tiny: 39MB → 74MB, medium: 769MB → 1.5GB, large: 1.5GB → 3.0GB).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

* docs(web): update model sizes across website pages

Sync whisper.cpp size references on gpu-acceleration, compare, whisper-model-guide, offline, and homepage with corrected download sizes.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
2026-06-06 16:54:21 -07:00
3f5a5effff feat(vad): add Silero VAD and drop silence-only buffers (#447)
* feat(vad): replace amplitude-based VAD with Silero neural network

Replace the simple amplitude threshold VAD with Silero VAD, a lightweight
neural network model that classifies audio as speech/non-speech. This
addresses the root cause of #302 (silence not stopping recording) and

- Add silero_vad.py wrapper using ONNX Runtime with bundled Silero v5 model
- Accumulate 512-sample chunks with 64-sample context window per official API
- Map existing vad_sensitivity (1-5) to Silero thresholds (0.8-0.3)
- Use max() across sub-chunks to avoid missing speech onsets
- Fall back to amplitude VAD when onnxruntime is unavailable
- Add onnxruntime as optional dependency (pip install vocalinux[vad])

Closes #344

* address review: add tests, LICENSE, logging, validation fixes

- Add unit tests for SileroVAD (process, reset, fallback, sensitivity mapping)
- Add MIT LICENSE for bundled Silero VAD model in data/
- Log which VAD backend is active on init
- Validate chunk length in SileroVAD.process()
- Skip is_speech check until a full Silero chunk is processed
- Add thread safety note to SileroVAD docstring
- Document resampling rate effect on VAD resolution
- Comment explaining why load_silero_vad() catches broad Exception

* address review: bundle license, document [vad] extra, surface backend in UI

- Pack data/LICENSE into the wheel (pyproject package-data) so attribution
  travels with the model
- README: short note on enabling neural VAD via vocalinux[vad]
- Settings: VAD Sensitivity row subtitle shows the active backend; if
  onnxruntime is missing, an info-row beneath the group spells out the
  install command and the restart requirement
- silero_vad.is_silero_available() probes onnxruntime + model presence
  w/o instantiating an InferenceSession
- CI installs .[dev,vad] so Silero paths get exercised
- Integration test for _record_audio Silero branch (mocked pyaudio +
  scripted SileroVAD), covering silence flush, speech reset, and
  sensitivity threshold mapping at sens=1 vs sens=5
- Tests no longer skip when other modules globally mock numpy: pop the
  top-level numpy ref so a fresh import gives the real package, and
  swap sys.modules["numpy"] inside the _record_audio call so the lazy
  import inside the function picks up real numpy too

* fix(vad): drop silence-only recording buffers

* test(vad): align stop buffer expectations

* test(vad): preserve real numpy module

* fix(install): install vad support opportunistically

* test(vad): cover recognition manager vad edges

---------

Co-authored-by: Sbenazar <127324689+Sbenazar@users.noreply.github.com>
2026-06-02 12:43:51 -07:00
Jatin K MalikandGitHub b3c73dd872 chore(release): prepare v0.11.0-beta (#440)
- Bump version from 0.10.2-beta to 0.11.0-beta
- Update all version references across codebase
- Add What's New section for v0.11.0-beta in README and docs/UPDATE.md
- Add v0.11.0-beta entry to website changelog
- Update SECURITY.md supported versions to 0.11.x
- Update website schema, badge, and package version
- Update RELEASE_PROCESS.md version history table
2026-05-30 16:52:02 -07:00
Jatin K MalikandGitHub 166bb8c49a chore(release): prepare v0.10.2-beta (#394)
- Bump version from 0.10.1-beta to 0.10.2-beta in version.py
- Update README.md What's New section with v0.10.2 highlights and bug fixes
- Update SECURITY.md supported versions table
- Update docs/UPDATE.md with v0.10.2 release notes
- Update docs/RELEASE_PROCESS.md version history table
- Update web/src/app/page.tsx softwareVersion and version badge
- Update web/src/app/changelog/page.tsx with v0.10.2 release entry
- Update web/package.json and web/package-lock.json to 0.10.2

Key changes in this release:
- Non-ASCII text injection via ydotool clipboard fallback (#376)
- IBus detection on Wayland without legacy env vars (#381)
- IBus engine process startup fix (#361)
- Missing deps for Pop!_OS and Ubuntu 24.04+ (#379)
- Systematic code quality refactor (#377)
- Redesigned website OG image (#392)
2026-04-08 13:43:22 -07:00
Jatin K MalikandGitHub c1f12db845 chore(release): prepare v0.10.1-beta (#358)
* chore(release): prepare v0.10.1-beta

* chore(release): update release notes with new fixes from main
2026-03-30 00:31:08 -07:00
84ec79c769 chore(release): prepare v0.10.0-beta (#345)
* chore(release): prepare v0.10.0-beta

Bump versions and release references across app, docs, installer, and website for the next beta release. Add v0.10.0-beta release notes entries covering reliability fixes and CI/test improvements since v0.9.0-beta.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs(release): align Python baseline references to 3.9+

Synchronize stale Python 3.8 references in agent guidance and distro dependency docs/scripts with the current 3.9+ minimum used by project metadata and release docs.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-25 23:31:26 -07:00
Jatin K MalikandGitHub fa17b88f74 chore: bump minimum Python from 3.8 to 3.9 (#336)
* chore: bump minimum Python from 3.8 to 3.9 and adopt PEP 585 builtins

- Update requires-python, classifiers, mypy target, and black target in pyproject.toml
- Replace Python 3.8 with 3.9 in CI matrix and nightly workflow
- Replace typing.List/Dict/Tuple/Set with builtin list/dict/tuple/set (PEP 585)
- Update all 3.8 version references in README, docs, website, and install.sh
- Fix test_wayland_no_tools to mock IBus availability
- Remove List from common_types re-exports and update test

* style: reformat test files for Black 26.x and pin version in CI

Black 26.x introduced parenthesized context manager formatting.
Reformat 7 test files and pin Black>=26,<27 in CI to prevent
future drift from unpinned version upgrades.
2026-03-21 12:15:10 -07:00
Jatin K MalikandGitHub f24674a4e8 docs: improve project description with narrative intro (#325)
* docs: improve project description with narrative intro

- Replace the one-liner README intro with a more compelling narrative
  that highlights key differentiators: offline, open source, multi-engine,
  GPU-accelerated, and privacy-first
- Update version.py __description__ to a more descriptive one-liner

* docs: replace all em-dashes with hyphens/commas/colons

Remove all em-dash (—) characters from README.md, replacing them
with contextually appropriate alternatives (hyphens, commas, colons).
2026-03-16 15:44:44 -07:00
Jatin K MalikandGitHub 23e07e7e19 docs: add star history chart to README (#318) 2026-03-14 19:18:07 -07:00
Jatin K MalikandGitHub 2d85afee70 feat(docs): add Voca Ecosystem section to README and website (#317)
* feat(docs): add Voca Ecosystem section to README and website

Add cross-project ecosystem shoutouts linking VocaLinux, VocaMac, and
VocaWin. README gets a table with platform, project, website, GitHub,
and status columns. Website gets animated cards with platform logos,
tech badges, status indicators, and links.

Uses simpleicons CDN for Apple logo and inline SVG for Windows logo
(simpleicons CDN does not serve a Windows icon).

* feat(web): UI refinements — terminal install boxes, contrast fixes, wider card grids

- Replace CodeBlock components with terminal-style command boxes (traffic-light dots, copy button, dark bg)
- Fix dark mode contrast: add dark:text-black to badges and buttons on green backgrounds
- Header: replace GitHub icon with filled yellow Star icon next to star count
- Hero buttons: rename and reorder (Install Now, We're Open Source, Use Windows or Mac?)
- Engine section: widen container from max-w-5xl to max-w-7xl to match features
- Ecosystem section: add VocaLinux 'You are here' card, widen from max-w-4xl to max-w-7xl
- Fix Windows icon color to official Microsoft Fluent blue (#0078D4)
- Remove unused CodeBlock import

* feat(web): link sub-pages, reorder cards, restyle hero, update FAQ, remove em-dashes

- Add href prop to FeatureCard: 6 tiles link to /offline/, /use-cases/,
  /gpu-acceleration/, /shortcuts/, /wayland/, /for-developers/
- Engine section: reorder to Whisper > whisper.cpp (center) > VOSK,
  move 'Compare all engines' to centered link below cards
- whisper.cpp card keeps 'GPU acceleration' link
- FAQ answers: convert to ReactNode with inline links to sub-pages,
  fix 6 stale answers (distros, requirements, languages, shortcuts,
  voice commands, engine switching)
- Hero buttons: GitHub-dark 'We're Open Source', ghost 'Use Windows
  or Mac?'
- Ecosystem: reorder to VocaMac > VocaLinux (center) > VocaWin,
  change badge from 'You are here' to 'Beta'
- Remove all em-dashes (9 occurrences)
2026-03-14 18:03:10 -07:00
Jatin K MalikandGitHub 44af1703c6 fix(docs): point all install curl URLs to main/install.sh (#314)
The install.sh on main now dynamically resolves the latest release tag
via GitHub API (merged in PR #313), so pinning to a specific release tag
in install commands is no longer needed — and was causing users to run
the old hardcoded installer.

Update all curl install command URLs across docs, code, and website from
versioned tags (v0.9.0-beta, v0.8.0-beta) to main/install.sh:
- README.md (4 URLs + note text)
- docs/INSTALL.md (2 URLs + note text)
- docs/UPDATE.md (2 URLs)
- docs/DISTRO_COMPATIBILITY.md (1 URL)
- tests/distro-testing-checklist.md (1 URL)
- src/vocalinux/main.py (1 URL)
- web/src/app/page.tsx (remove dynamic release fetch, hardcode main)
2026-03-14 14:16:38 -07:00
Jatin K MalikandGitHub baeee19f17 chore(release): prepare v0.9.0-beta (#310)
* chore(release): prepare v0.9.0-beta

- Bump version from 0.8.0-beta to 0.9.0-beta
- Update README What's New section with new features and bug fixes
- Update all install script URLs to v0.9.0-beta
- Add v0.9.0-beta What's New section to docs/UPDATE.md
- Update SECURITY.md supported versions (0.9.x supported, 0.8.x dropped)
- Update website schema softwareVersion and nav badge to 0.9.0
- Update website featureList with new sound effects and clipboard features
- Add v0.9.0-beta entry to changelog page
- Update web/package.json version to 0.9.0
- Add v0.9.0-beta row to RELEASE_PROCESS.md version history

* docs(readme): add contributors avatar grid via contrib.rocks

* feat(about): add Changelog link to About dialog

* Revert "feat(about): add Changelog link to About dialog"

This reverts commit 15e0984f516caccb14a0609e96d5fb6870ea247e.
2026-03-14 13:53:22 -07:00
Jatin K MalikandGitHub 0469defae6 chore(release): prepare v0.8.0-beta (#280)
* chore(release): prepare v0.8.0-beta

* docs(web): align release messaging with v0.8.0-beta features

* docs(web): tighten homepage messaging for v0.8.0-beta
2026-02-28 20:58:55 -08:00
Jatin K MalikandGitHub 6e02e928ae chore(release): prepare v0.7.0-beta (#255)
* chore(release): prepare v0.7.0-beta

## Version Bump (v0.6.3-beta → v0.7.0-beta)

This is a major beta release with significant new features including autostart support, tabbed settings, and improved GPU detection.

### Core Version Files
- Updated src/vocalinux/version.py to 0.7.0-beta
- Updated pyproject.toml classifiers (already correct - Beta)

### Documentation
- Updated README.md with new features, bug fixes, and version references
- Updated docs/INSTALL.md with v0.7.0-beta install commands
- Updated docs/UPDATE.md with comprehensive 'What's New' section
- Updated SECURITY.md supported versions table (0.7.x now supported)

### Website
- Updated web/src/app/page.tsx version badge (v0.7.0 Beta)
- Updated web/src/app/page.tsx softwareVersion schema
- Updated web/package.json version to 0.7.0
- Updated web/src/app/changelog/page.tsx with v0.7.0-beta release entry

### Other Updates
- Updated install.sh default tag to v0.7.0-beta
- Updated src/vocalinux/main.py error message install command
- Updated AGENTS.md branch naming example

## Changes Since v0.6.3-beta

### New Features (13 commits)
- Autostart on login support via XDG autostart
- Tabbed settings dialog with 5 organized tabs
- Intel GPU compatibility detection with automatic CPU fallback
- Single instance prevention
- Evdev device management to prevent CPU spin
- Improved GPU detection avoiding false positives
- IBus fallback when daemon not running
- Fedora dnf check-update fix
- Web SEO - 7 new optimized pages

### Contributors
- Jatin K Malik (maintainer)
- Antoine Monnet (contributor)
- jatinkrmalik (contributor)

### Bug Fixes
- #254: Improved GPU detection to avoid false positives
- #251: Skip IBus setup when daemon not running
- #243: Prevent dnf check-update from exiting script on Fedora
- #240: Raise exception on IBus setup failure
- #234: Removed leading space from first speech transcription
- #242/#253: Removed disconnected evdev devices to prevent CPU spin

## Verification
- [x] Lint passed
- [x] Black formatting passed
- [x] isort check passed
- [x] Version imports correctly as 0.7.0-beta

* docs: update version history in RELEASE_PROCESS.md

Add entries for 0.6.0-beta through 0.7.0-beta to the version history table.
2026-02-22 21:30:05 -08:00
Jatin K MalikandGitHub 9886e8cb9d feat(ui): add auto-start on boot support (#207)
* feat(ui): add auto-start on boot support

- Add --start-minimized CLI flag for autostart entry
- Create autostart_manager.py to handle XDG autostart desktop entry
- Add autostart config option in config_manager.py
- Add Start on Login toggle in Settings dialog
- Add Start Minimized toggle in Settings dialog
- Add Start on Login checkbox in system tray menu
- Add first-run dialog to ask about autostart preference

Closes #184

* fix(test): add first_run: False to mock config settings

The tests were failing with StopIteration because main() now checks
for first_run and shows a dialog if True. By setting first_run: False
in the mock config, we skip the first-run dialog code path.

* fix(ui): harden autostart behavior across Linux sessions

Use XDG-compliant autostart paths and robust Exec command resolution, keep first-run prompt semantics correct, and fix GTK toggle handling so state changes are applied reliably.

* docs(autostart): document XDG startup model and limits

Clarify that Vocalinux uses desktop-session XDG autostart, not systemd services, and explain compatibility expectations for mainstream DEs versus minimal/custom WM sessions.

* feat(ui): add first-run quick-start guidance text

Expand the welcome dialog with concise first-time usage guidance and clear direction to the tray menu Settings entry while preserving the existing autostart decision flow.

* fix(uninstall): remove XDG autostart desktop entry

Ensure uninstall removes ~/.config autostart registration and reports leftover autostart entries during verification.

* fix(install): ignore defunct processes in running-check

Filter installer process detection to exclude defunct entries and installer/uninstaller shells so stale zombie rows do not block reinstall.

* fix(uninstall): ignore defunct processes in running-check

Use filtered process detection so zombie entries and installer shells do not trigger false running-process warnings during uninstall.
2026-02-21 15:06:20 -08:00