The medium and large entries carried the same 22-language table
verbatim. Hoist it into _BEST_AVAILABLE_LANGUAGES and give each entry a
dict() copy, so the two sizes keep independent mappings. Values are
unchanged (the old literals were asserted equal before the move).
requires-python is >=3.11, so the ImportError branch that guarded
importlib.resources.files is dead code. Import it at module scope and
keep only the failures files() can really raise.
The python37-compatibility rule still matches the import itself even
though 3.11 has files(). That is a false positive for this floor, so
the import carries a one-line nosemgrep.
scripts/generate-model-checksums.py downloads the URLs that come from
remote model listings (the VOSK model-list.json and Hugging Face
responses), and urlopen would follow a file: URL there. _https() now
refuses anything but https before each request. The md5 digest is only
compared against the published listing, not used for security, so it is
marked usedforsecurity=False.
The remaining findings are false positives for this codebase, and each
gets a narrow nosemgrep on its own line with the reason:
- text_injector.py: argv lists without a shell; dictated text sits
after "--" so it cannot be parsed as an option.
- layout_key_map.py: the KDE layout_memory.xml in the user's own session
directory, not remote input.
- check_runtime.py: module names come from the literal tuples above.
- sync_flatpak_deps.py, verify_release.py: fixed https://pypi.org
endpoint.
- web tests: walks this repo's own src/app tree; loopback dev-server
probe in a test.
urllib.request.urlopen also opens file: and ftp: URLs, and the gateway
base URL and pairing targets are not guaranteed to be http(s). Add
require_http_url() to gateway_embed/urls.py and call it before each
urlopen. Health probes turn a rejected scheme into the existing soft
error; pairing raises ValueError.
The urlopen calls themselves stay flagged by the dynamic-urllib rule,
so each carries a one-line nosemgrep for that rule that points at the
check.
Semgrep's missing-cooldown rules flag Dependabot and uv configs that
apply newly published releases immediately. Dependabot waits seven
days before proposing updates, and [tool.uv] sets exclude-newer to seven
days.
uv.lock was regenerated with uv 0.13.3 (the pinned version). The only
change is the [options] block that records the cutoff: the same 165
packages resolve, and all eight requirements/*.txt exports are
byte-identical to the committed files.
Semgrep's run-shell-injection rule flags ${{ github.ref_name }} and
${{ github.repository }} interpolated into run: blocks. The tag name is
attacker-influenced input (git allows $, ( and ; in ref names), so the
release upload steps now read both through step env and quote them.
The rung cutoffs cite ticket 19's transcribe peaks, but ticket 19 is
still open and its measurement is not in this repository. The code and
test docstrings now say the numbers are provisional calibration to
replace, rather than evidence. Also formats the niri guard tests to the
project line length.
Cover the one-time setup (the XBPS_SIGNING_KEY secret, the committed public
key and its fingerprint, the runner and token needs), the tag-push gates and
what the workflow publishes to the tag release and to latest, and the
checklist items for verifying the run. The template version and checksum
bump stays a normal pull request, never a bot commit to main, and now says
the checksum is the sha256 of the fork's own release asset.
The cherry-pick policy from ticket #30 was already in this file and is
enforced by tests/test_upstream_intake_policy.py. Correct what it names as
the retained internal module: it is vocalinux (src/vocalinux/), not
voculinux.
Commit the public half of the repository signing key as
packaging/void/repository-key.plist and show its fingerprint beside the
registration lines in the root README and the Void packaging README. The
test derives the fingerprint from the committed key with the xbps
definition (MD5 of the ssh-rsa blob) instead of trusting typed text, checks
the key is 4096-bit public material only, and ties the README, the
registration URL and the release workflow to it.
Clients now register the fork's rolling latest release on Gitea instead of
a per-tag upstream GitHub URL, and the first sync no longer passes -y, so an
unknown key is never accepted silently. The Void README also documents key
generation, the XBPS_SIGNING_KEY secret, the tag workflow and the pending
app-template checksum.
The signed repository is now published by the tag-triggered Gitea workflow,
so release.yml drops the build-xbps job, its place in the checksum job's
needs list, the xbps-repo artifact pattern, and the checksum lines for
files that no longer arrive. The release notes point at the Gitea release
instead of promising attached repository files.
The policy tests now assert the new shape: release.yml carries no xbps
job, and the Gitea workflow is the one place that runs repo.sh.
AGENTS.md layout now lists app_identity, legacy_import, model_ladder,
packaging/void, the perf protocol script, the Gitea workflows and the
niri doc, as its own maintenance rule requires.
USER_GUIDE orders Wayland autodetection wtype before ydotool, matching
the decided ladder, and says the portal is never tried on niri.
docs/NIRI.md states the niri first dictation (no prompt; typing goes
direct through wtype; IBus excluded) and points to the GNOME and KDE
section.
The app template fetched upstream's 0.18.5 archive, carried upstream's
homepage and maintainer, and renamed the launchers and desktop entry in
post_install. The fork's sdist already names them voculinux, so the
template now sources the fork's release asset and installs the names as
they are. The checksum is an explicit pending marker until the fork's
v0.18.5 release exists, which fails closed in xbps-src and never falls
back to the upstream digest.
depends now pulls in pipewire (capture), wtype (direct typing on niri),
wl-clipboard (clipboard), xdotool (X11 and XWayland) and pulseaudio-utils
(pactl), and drops ibus, which cannot inject on niri. Every name is
checked against the Void index.
INSTALL.msg states the niri first run plainly (no permission prompt;
typing goes direct), never points at the portal on niri, and drops the
IBus claim. The container smoke queries the fork's distribution name.
Tests assert the fork sources, the pending-or-pinned checksum, the
runtime helpers, the absence of ibus, and the niri wording.
The allowlist accepted any line that mentioned upstream, legacy, cmdline,
a dotted name or a path segment, so a user-facing old name could pass
by sharing a line with one of those words. Each rule is now scoped to a
retained surface: upstream repository slugs and labelled upstream prose,
dotted references to modules that exist under src/vocalinux, import and
-m forms, retained class names, legacy import sources in the files that
implement or test the import, quoted package names in tooling and test
paths only, and the pre-rename guard in the Void container harness.
The sweep skips the .git worktree pointer file, and the allowlist itself
has behaviour tests: user-facing names are denied and retained surfaces
are kept.
Every lowercase identity constant is now derived from a single _SLUG, so
a rename is one edit. The values are unchanged (checked against
origin/main for all 33 constants and the user agent).
legacy_import: drop the unused subdirectory field from the payload
tuples, merge the four near-identical directory helpers, and use the
identity constants directly instead of aliases.
Docstrings: the retained package is vocalinux, not voculinux; the
one-time import is described as a legacy Vocalinux install.
nvidia-smi (vram_mib) and wtype (inject probe) ran without env=host_env(),
so under an AppImage bundle they inherit the bundle's library paths. The
AST guard now covers the measurement script as well as src/vocalinux, and
the script gains the module logger the Style rules require.
get_recommended_model() now keys to the backend the installed whisper.cpp
build actually has (detect_pywhispercpp_gpu_backend) and to free memory
measured at recommendation time: free VRAM on a discrete GPU for a
Vulkan or CUDA build, free system RAM otherwise. The result is a rung of
the model ladder, so a Vulkan-capable Nvidia card reaches the ladder
instead of the total-memory tiers, and unquantized turbo, the large
family and medium are never a default.
Manual selections are untouched. The informational hardware probe no
longer decides the model. Dead VRAM-total parsing is removed.
free_memory_for_backend() holds the source choice; the floor-rung map is
shared by rung selection and step-down.
A version tag push builds every Void template through packaging/void/repo.sh
(podman, pinned Void glibc container), signs the repository, and publishes
the complete glibc x86_64 set to the tag's release and to the rolling latest
release that the client registration URL serves.
Gates, each failing the job before anything publishes: the tag must equal
v plus __version__ exactly, XBPS_SIGNING_KEY must be set, the staged
repository must hold every class of file and nothing but glibc x86_64
data, every package must carry its signature, and the signing key must have
the pinned fingerprint. The key lives in a 0600 temp file that an
always-run step removes. Nothing commits, pushes, or bumps templates.
The offline tests run the workflow's own gate, verify, build and publish
scripts against a stateful stand-in for the Gitea release API.
Guards the star-count removal, the fork source host constant, the Arch AUR
wording, the unlinked unpublished Snap and AUR cards, the privacy claims and
the install-page rule that the old name only appears with an upstream label.
PRODUCT.md promises no usage telemetry in the installed app, a guaranteed
whisper.cpp default, best-effort extras and audio leaving the machine only
through a user-configured remote API. Copy that went further is corrected:
"Zero Data Collection", "Truly Private" and the maintainer-cannot-see claim
are gone, the hero and ribbon say "no app telemetry" because the site itself
loads analytics, and the engine lists name whisper.cpp as the default with
the rest as extras. The privacy, FAQ, offline and home pages now say the app
uses the network for model downloads and the update check, without audio or
transcripts.
The Arch guide said Arch users can install Voculinux from the AUR while the
install and home pages say the fork AUR packages are not published yet.
The Arch description, intro, prerequisites and notes now say there is no
AUR install path today. The Snap and AUR cards on the install and home pages
no longer link to package pages that do not exist, and the nixos and flatpak
pages stop listing the AUR as an option.
The header badge fetched the star count of VocaHQ/vocalinux at build time
and labelled it as Voculinux's. The fetch and the count are gone; the
header, footer and social "source" links now go to the fork repository at
git.bongbetic.com/xavierk/voculinux, as do the issue links, the docs
anchors, the home page JSON-LD and the xbps release card.
Upstream GitHub stays only where it is the real artefact or provenance and
is labelled as such: the install script, the AppImage release card, the
upstream card and the changelog release links. The changelog now says its
entries are upstream history, the open-source page no longer claims
VocaHQ membership or an active GitHub community, and the organization
JSON-LD drops the upstream author as founder. DESIGN.md and PRODUCT.md
follow.
The install page spelled the old binary name on a line with no upstream
label, which fails the offline naming sweep. The launch note now leads
with voculinux and marks the old name as upstream on the same line.
Autodetection on niri now never probes or selects the RemoteDesktop
portal, and the ibus-wayland bridge exception no longer reopens IBus
there. Key events after startup resolve wtype before ydotool, matching
_check_dependencies and the decided ladder.
conftest scrubs NIRI_SOCKET so tests modelling other desktops are not
affected when run inside a niri session.
Replace the self-referential <repo-url-from-release-notes> placeholder
in the root README, the release-notes template, and the Void packaging
README with the concrete per-tag download prefix the build-xbps job
attaches the signed repo to. Static docs default TAG to the current
version; release.yml renders github.ref_name at publish time.
Fixes#29
Extend the AC1 honesty tests to the faq install answer and the
faster-whisper/parakeet install commands, and add fork-status plus
upstream-install-script disclosure on all three surfaces.
Fixes#24
Ticket #31 review found startup and demote paths preferring ydotool
over wtype, with a KDE ydotool-first exception, contradicting the
decided order in spec #16 (portal first where a backend implements
it, then direct keysym typing, then the virtual-input tool, then
XWayland-only injection, then manual paste).
- Auto-selection is now portal, wtype, ready ydotool, daemonless
ydotool, xdotool on every desktop including KDE; the __init__ wtype
probe validates wtype and demotes on compositor rejection.
- Portal-deny demotion, IBus-fallback switch, XWayland recovery, and
a new wtype runtime-failure retry all follow the same rung order
with partial-type accounting preserved.
- Ladder suite grows to 14 tests pinning KDE portal selection,
wtype-before-ydotool selection, and each demotion trigger.
- USER_GUIDE states the full rung order and portal-first on KDE.
Add build-xbps tag job to release.yml: verifies the tag against
src/vocalinux/version.py, fails closed when XBPS_SIGNING_KEY is unset,
builds and signs via podman-only repo.sh, and attaches packages,
signatures, repodata, and client key files to the release. Fold the
xbps-repo artifact into publish-checksums (manifest + SHA256SUMS).
Document the Void install in the root README (glibc x86_64 scope,
fingerprint check, third-party repo caveat) and the post-tag template
version/checksum bump as a pull request in docs/RELEASE_PROCESS.md.
Proof: local podman run with a throwaway RSA4096 key built all four
templates, signed packages + repodata, and verified voculinux installs
from the signed repo in a clean rootdir (fingerprint
eb:29:5d:9e:5c:94:c1:63:ae:35:cd:35:db:7a:28:da).
Every download/install surface now states that fork AppImage, .deb/.rpm,
Flatpak, Snap, AUR and xbps artefacts are not published yet, labels
upstream GitHub Releases links as upstream, corrects 'Then launch
voculinux' to the upstream vocalinux binary the install script ships
today, and softens the NixOS xbps line to future tense. Adds AC1 honesty
tests to voculinux-rebrand.test.ts.
Fixes#24
Both model-download call sites built the User-Agent string separately:
recognition_manager used a hardcoded literal while settings_dialog
interpolated APP_ID. Add app_identity.user_agent() and use it in both,
with a test pinning the shared definition.
Fixes#17
q8_0 threshold becomes 1644 MiB (1132+512) and q5_0 becomes 1358 MiB
(846+512) per the recorded baseline recommendation, replacing the
on-disk-size proxies. Tests pin the measured values and the 1644/1358
boundaries.
Build every template in smoke-gate order, index the full repository and
sign packages plus metadata with the RSA4096 key, in the pinned Void
container via podman. Fail-closed without a key: no key file, no repo.
Ticket #29 (needs #27, #28).
Ticket xavierk/voculinux#28, needs #27. One documented command
(packaging/void/smoke.sh, just void-smoke) lints, builds, installs
and smoke-tests every template under packaging/void/srcpkgs in
dependency order in the pinned Void container via podman, failing
fast naming the package with the harness echoing each stage.
The gate caught three latent breaks in the per-package harness and
the app template, fixed here:
- container-main.sh scoped the libggml scan to python3-pywhispercpp
and gave the leaf packages their own import smokes (pynput by
presence: no display in the container), failing loudly for
packages without a smoke recipe;
- voculinux template drops the deprecated wrksrc override (xbps-src
renames the single-top-dir archive itself; xlint rejects wrksrc)
and builds the PEP 517 wheel (the sdist ships no setup.py);
- post_install promotes the pre-rename sdist names (desktop entry
content, icons, /usr/bin launchers) to the renamed identity, and
the payload smoke rejects pre-rename leftovers in OS-visible paths.
Offline policy tests (tests/test_void_smoke_gate.py) pin the gate to
the template set, the app-last order, podman-only pinned inputs and
per-package failure identity; the #27 policy tests and the rename
sweep cover the harness and template contracts.
Install one-liners still fetch the upstream script, so each install
entry point now says so plainly (Nix-page precedent): upstream
installs Vocalinux, not Voculinux, and fork release artefacts are not
published yet. Homepage xbps card no longer claims signed repository
data ships with every release while the packaging pipeline (#29) is
open. Also 'VocaHQ remote' -> 'Flatpak remote' on the install page.
Refs #24
Ticket xavierk/voculinux#27, built on #18 (rename) plus the #25/#26
dependency templates. The template builds the app from the canonical
checksum-verified release sdist, depends on Void's interpreter, GTK,
desktop bindings and packaged Python libraries, and installs the
renamed desktop entry, icons and a packaged-install marker. No speech
models, no vendored wheels, no pip at build or install time.
Packaged installs keep background update checks as a signal, but every
update affordance presents the package-manager path
(src/vocalinux/utils/packaging.py). Also corrects the Void distro
inventory (Ayatana provider name; ydotool marked absent) and regens
the installer map.
Names, wordmarks, package and install references move to voculinux;
site domain to voculinux.com with renamed public assets. Layout keeps
Carbon spacing/type/motion discipline remapped to the house palette
(teal interactive, warm paper, system stacks, red reserved). Header
and footer gain Bongbetic attribution chrome linking hosted brand
assets; no brand binaries vendored. Engine copy states whisper.cpp as
guaranteed default, others as best-effort extras, remote API as
user-configured with audio leaving the machine. Nix page carries a
fork-status note (upstream flake installs Vocalinux).
Refs #24