fix(app): CUDA toolkit detection, niri IBus pin warning, Gitea update checks, legacy dictionary path #36

Merged
xavierk merged 6 commits from fix/app-post-merge into main 2026-11-06 14:38:44 +00:00
Owner

Description

Four app fixes from the Voculinux post-merge list, one Conventional Commit per item:

  1. CUDA toolkit detection (ticket #20). cuda_toolkit_ready() only accepted nvcc on PATH, so a session started before the CUDA profile snippet ranked Vulkan above a CUDA build. A complete toolkit is now also recognised under CUDA_HOME, CUDA_PATH or /usr/local/cuda* (nvcc, include/cuda_runtime.h, libcudart in the architecture-matching target). The backend order names only backends the installed build compiled in, and _load_whispercpp_model passes the detected build.
  2. niri IBus pin (spec #16, injection section). An explicit ibus pin is still honoured on niri. The one WARNING it logs now says IBus on niri can report success while text is silently dropped, instead of the generic compositor wording.
  3. Update checker (spec #16, Void packaging; ticket #27). Source installs query the Gitea release API for xavierk/voculinux (tag_name, html_url, body), and only that repository's release pages are trusted links. The GitHub API and its HTML fallback are removed. Packaged installs (the xbps marker) make no release request: fetch_latest_release returns before importing requests, and Settings -> About shows that updates arrive via sudo xbps-install -Su. docs/UPDATE.md is updated.
  4. Migrated dictionary path (ticket #18). A stored dictionary path that names an importer-owned legacy file is rewritten in the copied config to that file's new location, so edits never land in the legacy directory. Paths outside the legacy payload are kept as stored.

Reading of "were copied" in item 4

The rewrite covers every importer-owned legacy file (the config payload and the restore token), whether or not this run copied it. A literal "copied this run" rule left the legacy path in place when the user never created a legacy dictionary, or already had a new dictionary.txt, so the first edit was written back to the legacy directory. Two tests reproduce those cases.

Still not covered: another file inside the legacy directory that the config names but the importer does not own (for example a custom my-terms.txt). Its path is kept as stored.

Packaged wording

The packaged update message uses the spec's sudo xbps-install -Su. packaging/void/srcpkgs/voculinux/INSTALL.msg still says sudo xbps-install -Syu voculinux and is not changed in this PR.

Related issue

Refs #16 (spec), #18, #20, #27. Not "Fixes": #16 is closed.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactor
  • Tests
  • Packaging / CI

Checklist

  • Code follows project style (Black, isort, flake8)
  • Documentation updated when user-facing behavior or install steps change (docs/UPDATE.md)
  • Tests added or updated for the change
  • Touched test files pass. The full suite has the same 145 failing or erroring test IDs on origin/main (checked against a clean export of origin/main), none new
  • Conventional commit message style

Screenshots (if applicable)

Not applicable.

Notes for reviewers

  • Real hardware (item 1). RTX 2050 (3711 of 4096 MiB free, compute capability 8.6), toolkit at /usr/local/cuda-13.2 through the /usr/local/cuda symlink, nvcc not on PATH, environment cleared. Before this change cuda_toolkit_ready() was False in both venvs, and the CUDA-built venv ordered vulkan -> cpu. After it, the Vulkan-built venv gives vulkan -> cpu and the CUDA-built venv gives cuda -> cpu.
  • Gitea repository state. xavierk/voculinux is private and has no releases. Anonymous releases/latest returns 404, so source installs will report no release until the repository is public and tagged.
  • Pre-existing failures. The full pytest run here (GTK installed, gi mocked by several test modules) reports 145 failing or erroring test IDs, identical to origin/main; tests/test_settings_dialog.py::TestPasteLongTextPreference::test_switch_loads_and_saves is one of them.
  • Left as upstream references (out of scope here). The About page project, issues and wiki links; the docs/UPDATE.md curl install lines; the GATEWAY_GIT_URL VocaGateway clone, which still points at upstream VocaHQ. version.__url__ is unchanged for the same reason.
  • preferred_backend_order feeds a log line only. Which backend loads is still decided by detect_pywhispercpp_gpu_backend().
## Description Four app fixes from the Voculinux post-merge list, one Conventional Commit per item: 1. **CUDA toolkit detection (ticket #20).** `cuda_toolkit_ready()` only accepted `nvcc` on PATH, so a session started before the CUDA profile snippet ranked Vulkan above a CUDA build. A complete toolkit is now also recognised under `CUDA_HOME`, `CUDA_PATH` or `/usr/local/cuda*` (nvcc, `include/cuda_runtime.h`, `libcudart` in the architecture-matching target). The backend order names only backends the installed build compiled in, and `_load_whispercpp_model` passes the detected build. 2. **niri IBus pin (spec #16, injection section).** An explicit ibus pin is still honoured on niri. The one WARNING it logs now says IBus on niri can report success while text is silently dropped, instead of the generic compositor wording. 3. **Update checker (spec #16, Void packaging; ticket #27).** Source installs query the Gitea release API for `xavierk/voculinux` (`tag_name`, `html_url`, `body`), and only that repository's release pages are trusted links. The GitHub API and its HTML fallback are removed. Packaged installs (the xbps marker) make no release request: `fetch_latest_release` returns before importing `requests`, and Settings -> About shows that updates arrive via `sudo xbps-install -Su`. `docs/UPDATE.md` is updated. 4. **Migrated dictionary path (ticket #18).** A stored dictionary path that names an importer-owned legacy file is rewritten in the copied config to that file's new location, so edits never land in the legacy directory. Paths outside the legacy payload are kept as stored. ### Reading of "were copied" in item 4 The rewrite covers every importer-owned legacy file (the config payload and the restore token), whether or not this run copied it. A literal "copied this run" rule left the legacy path in place when the user never created a legacy dictionary, or already had a new `dictionary.txt`, so the first edit was written back to the legacy directory. Two tests reproduce those cases. Still not covered: another file inside the legacy directory that the config names but the importer does not own (for example a custom `my-terms.txt`). Its path is kept as stored. ### Packaged wording The packaged update message uses the spec's `sudo xbps-install -Su`. `packaging/void/srcpkgs/voculinux/INSTALL.msg` still says `sudo xbps-install -Syu voculinux` and is not changed in this PR. ## Related issue Refs #16 (spec), #18, #20, #27. Not "Fixes": #16 is closed. ## Type of change - [x] Bug fix - [ ] New feature - [ ] Breaking change - [x] Documentation - [ ] Refactor - [x] Tests - [ ] Packaging / CI ## Checklist - [x] Code follows project style (Black, isort, flake8) - [x] Documentation updated when user-facing behavior or install steps change (`docs/UPDATE.md`) - [x] Tests added or updated for the change - [x] Touched test files pass. The full suite has the same 145 failing or erroring test IDs on `origin/main` (checked against a clean export of `origin/main`), none new - [x] Conventional commit message style ## Screenshots (if applicable) Not applicable. ## Notes for reviewers - **Real hardware (item 1).** RTX 2050 (3711 of 4096 MiB free, compute capability 8.6), toolkit at `/usr/local/cuda-13.2` through the `/usr/local/cuda` symlink, nvcc not on PATH, environment cleared. Before this change `cuda_toolkit_ready()` was False in both venvs, and the CUDA-built venv ordered `vulkan -> cpu`. After it, the Vulkan-built venv gives `vulkan -> cpu` and the CUDA-built venv gives `cuda -> cpu`. - **Gitea repository state.** `xavierk/voculinux` is private and has no releases. Anonymous `releases/latest` returns 404, so source installs will report no release until the repository is public and tagged. - **Pre-existing failures.** The full `pytest` run here (GTK installed, `gi` mocked by several test modules) reports 145 failing or erroring test IDs, identical to `origin/main`; `tests/test_settings_dialog.py::TestPasteLongTextPreference::test_switch_loads_and_saves` is one of them. - **Left as upstream references (out of scope here).** The About page project, issues and wiki links; the `docs/UPDATE.md` curl install lines; the `GATEWAY_GIT_URL` VocaGateway clone, which still points at upstream VocaHQ. `version.__url__` is unchanged for the same reason. - `preferred_backend_order` feeds a log line only. Which backend loads is still decided by `detect_pywhispercpp_gpu_backend()`.
xavierk added 6 commits 2026-11-06 14:33:21 +00:00
cuda_toolkit_ready() only accepted nvcc on PATH, so a session started
before the CUDA profile snippet ranked Vulkan above a CUDA-compiled build.
A complete toolkit is now also recognised under CUDA_HOME, CUDA_PATH or
/usr/local/cuda*, requiring nvcc, include/cuda_runtime.h and libcudart in
the architecture-matching target. The backend order only names backends
the installed build compiled in, so a Vulkan-only build never lists CUDA.

Refs #20
An explicit ibus pin (VOCULINUX_FORCE_BACKEND or text_injection.backend)
is still honoured on niri, as the documented escape hatch. The one warning
it logs now names niri and says IBus there can report success while text
is silently dropped, instead of the generic compositor wording.

Refs #16
Source installs look up releases on the Gitea repository
(git.bongbetic.com/xavierk/voculinux) through its JSON API and parse
tag_name, html_url and body. The GitHub API and the HTML scrape fallback
are removed, and only that Gitea repository's release pages are trusted
links.

Packaged installs (the xbps marker) make no release request at all:
fetch_latest_release returns before importing requests, and Settings
-> About shows that updates arrive via sudo xbps-install -Su.

Refs #16, #27
The one-time import copied config.json and dictionary.txt, but a stored
dictionary path that still named the legacy file kept pointing there, so
dictionary edits were written back to the legacy location. After the copy,
the new configuration copy now has its dictionary path rewritten when it
names a legacy file copied in this run. Only the new copy is written, and
a path chosen outside the legacy directory is kept as stored.

Refs #18
A stored dictionary path to an importer-owned legacy file was rewritten
only when this run copied that file. A user who never created a legacy
dictionary, or who already has a new dictionary.txt, kept the legacy path,
and the first edit was written back into the legacy directory. The path is
now rewritten to the file's new location whenever it names a payload file,
copied this run or not. Paths outside the legacy payload are kept as stored.

Refs #18
test(update): isolate the update checker tests from a packaged marker
CI / security (pull_request) Successful in 1m14s
CI / lint (pull_request) Successful in 21s
CI / ai-review (pull_request) Successful in 9s
474b522281
The update checker tests now patch the packaged-install check, so they do
not depend on /usr/share/voculinux/packaged being absent on the host. The
model ladder test for an unrequested cuda-without-toolkit order is dropped.

Refs #16, #20
xavierk merged commit 2a76793109 into main 2026-11-06 14:38:44 +00:00
Sign in to join this conversation.