The canonical sdist is built from the tag, but a second build of the same
commit differs in tar and gzip timestamps, so its digest is recorded from the
published asset, not from a rebuild. Correct the comments and docs that said
"reproducible sdist". No behaviour change.
xbps packages are zstd-compressed. The clean install image had no zstd, so
tar could not list the payload and the smoke failed on a package that was
fine. Install zstd in the install phase.
The sdist is built from the tag by the release path and never attached by
hand. The release PR sets version and _tag in the template; the checksum is
recorded by a pull request after the tag. Runner requirements, the three
container phases and the local dry run are documented.
- build-release.sh: POSIX-only checks (dash runs the release), a release form
is exactly X.Y.Z or X.Y.Z-alpha|beta|rcN, and the install smoke refuses a
package that has no smoke recipe.
- Tests: names and tag gate (exact match, committed template must agree), key
refusals before any container starts (fake podman records calls), the
render script pins only the build tree, podman wiring (only the sign phase
sees the key, and it has no network), the xbps ordering of pre-release
spellings, the workflow gates, tmpfs key staging, and the publish set
(sdist, packages, signatures, repodata, client key).
The signed Void release depended on a fork sdist attached to the release
before the tag existed, and the app template carried a PENDING checksum that
had to be filled by hand. Every release is now built from its tag alone:
- packaging/void/build-release.sh is the one release path. The Gitea workflow,
the local dry run and the smoke gate all call it.
- The canonical reproducible sdist is built from the tag with
scripts/build_reproducible_wheel.py (Python 3.11, pinned uv).
- render-voculinux.sh pins version, _tag and checksum in the container's build
tree only, and places the sdist where xbps-src resolves its distfile.
The committed template keeps a zero placeholder until the post-release
checksum pull request.
- xbps version is __version__ with the hyphen removed (0.19.0-beta becomes
0.19.0beta), which xbps sorts below the final release.
- Builds run without the key; signing runs with the key mounted read-only and
no network; the install smoke runs in a clean image without the key.
- The workflow gates the tag and the key before any container starts, writes
the key to a 0600 tmpfs file, and publishes only the staged set (sdist,
packages, signatures, repodata, client key).
- smoke.sh runs the same pipeline with a throwaway key.
Model recommendation keyed to the installed build and free memory, fork-sourced Void templates, signed xbps release workflow on Gitea with the pinned repository key, niri injection guard and wtype-first order, tightened naming sweep, web copy fixes, and CI security and duplication fixes.
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
Locks the ordered rungs without real compositors: portal first where a
backend implements it (GNOME), direct typing first on niri with IBus
excluded and no portal selected, deny demoting to direct typing with the
full dictation kept, terminal probe choosing Ctrl+Shift+V, held modifiers
delaying the XWayland paste, and clipboard manual paste as last resort.
USER_GUIDE states the niri first run (no prompt, typing goes direct,
never pin portal there) and the GNOME/KDE grant, persistence and deny
fallback under the renamed backend setting and override names.
Refs #31
Docs-only slice of ticket #22: include file, integration page, index
links. Tray-watcher observation stays open for hardware run (#32); no
probe code changed.
Refs #22
Alongside Toggle/Start/Stop, the renamed interface now publishes
dictation state (idle/listening/processing) as a StateChanged signal
and a readable State property, so status bars and scripts can follow
dictation without scraping the tray. Signals fire only on change, so
double start/stop emits no duplicates; command-line triggers behave
exactly as before.
Refs #21
Free memory picks the load-time rung (large-v3-turbo-q8_0 default,
q5_0 under 1086 MiB free, small/small.en floor) for unpinned default
configs; thresholds derive from catalog sizes plus the protocol's
512 MiB headroom. A manual pin is never overridden, and a failed load
steps one rung down and retries exactly once before surfacing.
CUDA ranks before Vulkan only with a complete architecture-matching
toolkit (nvidia-smi GPU, nvcc, compute capability >= 7.0); otherwise
Vulkan, then CPU. The driver-only CUDA recommendation now demotes to
CPU logic instead of naming an unreachable VRAM ladder.
Refs #20
The fork takes its own name everywhere a user can see it: binaries
(voculinux, voculinux-gui), desktop entry, autostart, tray, D-Bus
namespace (com.voculinux.Voculinux, no alias for the old name),
config/data/cache dirs, single-instance lock, IBus engine identity,
tray icons, resource prefixes, VOCULINUX_* environment names, and the
update-checker user agent. The internal Python module stays vocalinux
and the distribution metadata keeps the upstream URLs as provenance.
On first run a previous Vocalinux install's config.json, custom
dictionary, and portal restore token are copied once into the new
locations (new config always wins, no merge, no write-back); models
re-resolve through the pinned-checksum download path. An offline
naming-sweep test proves no old-name strings remain on user-visible
surfaces outside the allowlist.
Refs #18
Conflict in packaging/void/tool_checksums.txt (add/add with #25):
kept #26 rows (base-image digest + void-packages pin the kept
build.sh reads) with the #25 header reference folded in. #25's
base-image digest differed; flagged for re-pin on next bump.
BRAND_ACCENT single source with shade()-derived states; accent CSS
covers suggested-action buttons and the listening chip, installed at
USER priority from main().
Refs #23
Single app_identity module owns APP_NAME/APP_ID, D-Bus names,
desktop/icon/IBus names and related surfaces; 16 consumers import
from it with zero value changes. Deliberately excludes
settings_about and dictation_pad literals pinned by existing tests.
Refs #17