Commit Graph
98 Commits
Author SHA1 Message Date
Palash Debnath 65a535a638 fix: integrate current main and finish review requirements for #2080 2026-09-17 12:09:57 +05:30
Palash Debnath 715bbbde70 Merge branch 'velixio_dev' into fix/linux-electron-setup-sidebar 2026-09-17 01:41:14 +05:30
Palash Debnath 39d66d5299 Prepare v0.5.3 for Electron and the final Tauri update 2026-09-17 01:30:17 +05:30
velixio 10d086359c feat(workers): show remote telemetry 2026-09-17 01:08:38 +05:30
STINGandCursor 5bad0e765a fix(deps): cap pedalboard below the SIGILL wheels
0.9.21+ Linux wheels are built with -march=native and crash first
synthesis on many CPUs. Keep the last known-good 0.9.20 in lock.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 05:03:08 +03:00
Palash Debnath df81bcd1ac fix(deps): raise protobuf and transformers bounds in pyproject too
The floors test checked only uv.lock, and pyproject still allowed
transformers>=5.5.0 and protobuf>=4.25. A fresh resolution, or an install
without the lock, could still pick a release below the advisory fixes.
The manifest now requires transformers>=5.10.0 and protobuf>=5.29.6. The
lock already resolved 5.15.1 and 7.36.0, so no package version changes;
only the recorded requirements do.
2026-09-10 14:35:31 -07:00
Palash Debnath 0ed7d2ec22 chore(release): prepare v0.5.2 (#1761)
Synchronize VoiceStudio release metadata, lockfiles, installers, container references, documentation, and the dated v0.5.2 changelog after all planned fixes landed.
2026-09-02 10:26:14 +05:30
Palash Debnath 97bfbfecd1 chore(release): prepare v0.5.1 (#1688)
Prepare the tested main branch for the v0.5.1 patch release with synchronized version sources, mirrors, lockfiles, release notes, and install guidance.

Closes #1687.
2026-08-28 11:27:59 +05:30
Palash Debnath 0d3c81b596 feat(gguf): add Linux ARM64 runtime support (#1641)
Add linux-aarch64 platform detection, Vulkan-preferred source builds with CPU fallback, ARM64-safe PyTorch dependency markers, native artifact CI, regression coverage, and synchronized architecture documentation.
2026-08-23 15:07:52 +05:30
Palash Debnath 3eeed0cfe9 chore: refresh application dependencies (#1625)
Refreshes frontend, tooling, and Python dependencies; regenerates the frozen lockfiles and worker protocol stubs. Keeps compatibility caps for FastAPI, Oxlint, and Vitest where newer releases break repository contracts. Updates the Uvicorn bind-failure regression test for its new nonzero exit code. Fully tested after merging current main.
2026-08-21 10:30:49 +00:00
Palash DebnathandClaude Fable 5 9184d7d625 chore: bump to 0.5.0 (#1540)
* chore: bump to 0.5.0

Owner-requested minor bump. package.json is the source of truth; the
three mirrors (Cargo.toml, pyproject.toml, _FALLBACK_VERSION), the three
lockfiles and the branding pin move in lockstep, and the accumulated
Unreleased section becomes the curated 0.5.0 release notes — quiet
Highlights first, one-liner subsections after, duplicates folded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: fresh README for the VoiceStudio era; 0.5.0 notes wear the release

README: 551 lines from 656 — a What's-new-in-0.5.0 section with real
captures, the engine tables corrected to the actual 16 TTS registrations,
a stale Settings path and a broken Colab link fixed, roadmap/FAQ/credits
trimmed to what earns its place.

Release notes: the quick-switch GIF and catalogue/gallery screenshots,
captured from the running app during the pre-bump test pass, embedded
after the Highlights; #1542's gallery work and the ffmpeg CI fallback
recorded in their subsections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: the feature inventory's Remote Model Downloads mention survives the README trim

check-docs-drift requires every docs/features.yaml name verbatim in the
README; the overhaul folded the phrase away. It now lives in the remote
workers feature line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: one blockquote, and an architecture claim that survives the opt-ins

CodeRabbit on #1540: MD028 blank line inside adjacent blockquotes, and
'every layer is on your machine' contradicted the opt-in remote paths
documented two sections away — it now states local-by-default with the
opt-ins named.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-13 23:50:23 +00:00
velixio 7924b35f8d Merge remote-tracking branch 'origin/main' into feat/worker-protocol-v1 2026-08-10 21:40:44 +05:30
velixio e5bd11bf85 Merge remote-tracking branch 'origin/main' into feat/worker-protocol-v1 2026-08-10 14:18:48 +05:30
velixio 43de1c794c feat(workers): remote GPU workers over a versioned gRPC protocol
Send individual jobs to GPUs on your other machines while everything else
stays local. Opt-in, off by default: with the toggle off there is no
listening socket, no certificate and no background loop.

Design follows remote/goal_v2.md, the council-revised goal doc. The
decisions that shaped the code, and why:

* A disconnect is an unknown outcome, not a failure. The original design
  reassigned on disconnect while also describing the case where the worker
  had already finished — following both guarantees duplicate execution. An
  attempt now holds a grace window; a worker returning inside it commits
  its result and no second attempt is ever made.
* At-least-once execution, exactly-once result commit. The result is
  persisted BEFORE it is acknowledged, so a crash between the two cannot
  silently lose a finished render.
* Deadlines are phased (accept -> model load -> execute -> deliver) and
  liveness is a progress lease. The old fixed 30s execution budget was two
  orders of magnitude below what this product actually does; silence is
  the failure signal, not slowness.
* Capacity is derived from free VRAM, never configured: a static value
  corrupts output under torch.compile thread affinity (#315) and aborts
  the process on small cards (#567).
* A circuit breaker replaces the reliability-score/quarantine machinery,
  which had no recovery path (no probation workload exists in a TTS
  product) and penalised consumer networks for existing.
* Identity is a keypair the worker generates and never sends. A
  server-assigned id is a name, not an authenticator, so revocation of one
  would be theatre. Enrollment tokens are single-use and carry the control
  plane's certificate fingerprint for pin-on-first-use.

Adds the domain core, scheduler, durable task store, gRPC transport,
worker agent, management API, Settings panel, and docs. Protobuf reserves
the tenant/trace/usage fields a hosted control plane would need, since
adding them later means upgrading a whole fleet.

Includes tests for the failure paths that matter: duplicate delivery,
stale-session fencing, reconnect reconciliation, grace expiry, breaker
attribution, and a real end-to-end TLS round trip.
2026-08-10 14:18:42 +05:30
debpalash a540354cb7 Merge remote-tracking branch 'origin/main' into codex/pr1442 2026-08-10 08:48:33 +00:00
debpalash 501450e8ec Merge remote-tracking branch 'origin/main' into codex/pr1442 2026-08-10 07:21:53 +00:00
debpalash 705544df96 Merge remote-tracking branch 'origin/main' into fix/dependabot-security
# Conflicts:
#	CHANGELOG.md
2026-08-10 04:30:23 +00:00
debpalash bebe9c6e26 Merge remote-tracking branch 'origin/main' into test/pillow-video-context 2026-08-10 03:44:42 +00:00
debpalash 67ccfafbd3 Merge remote-tracking branch 'origin/main' into test/pillow-video-context 2026-08-10 02:43:17 +00:00
debpalash ac610b2aa4 Merge remote-tracking branch 'origin/main' into codex/pr-1451 2026-08-10 02:43:14 +00:00
debpalash c642379c3c fix(video): declare Pillow runtime floor 2026-08-10 02:11:37 +00:00
debpalash aaba64e000 Merge remote-tracking branch 'origin/main' into codex/pr-1451 2026-08-10 02:09:50 +00:00
debpalash da31ef9aec Merge remote-tracking branch 'origin/main' into review/pr-1465 2026-08-10 02:09:35 +00:00
debpalash e806470324 Merge remote-tracking branch 'origin/main' into test/pillow-video-context 2026-08-10 02:09:29 +00:00
debpalash c4e13fc07c Merge remote-tracking branch 'origin/main' into review/pr-1465 2026-08-10 01:48:07 +00:00
debpalash 3dde7b52db Merge remote-tracking branch 'origin/main' into codex/pr-1450 2026-08-10 01:39:04 +00:00
dependabot[bot] 6fd4db8779 chore(deps): bump pillow from 12.2.0 to 12.3.0
Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.2.0 to 12.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/12.2.0...12.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 01:26:30 +00:00
debpalash c6f7167d06 Merge remote-tracking branch 'origin/main' into codex/pr-1449 2026-08-10 01:08:02 +00:00
dependabot[bot] 82a7039988 chore(deps): bump yt-dlp from 2026.6.9 to 2026.7.4
Bumps [yt-dlp](https://github.com/yt-dlp/yt-dlp) from 2026.6.9 to 2026.7.4.
- [Release notes](https://github.com/yt-dlp/yt-dlp/releases)
- [Changelog](https://github.com/yt-dlp/yt-dlp/blob/master/Changelog.md)
- [Commits](https://github.com/yt-dlp/yt-dlp/compare/2026.06.09...2026.07.04)

---
updated-dependencies:
- dependency-name: yt-dlp
  dependency-version: 2026.7.4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 00:54:03 +00:00
debpalash d8268ca99c fix(pockettts): gate unsupported Intel Mac wheels 2026-08-09 21:26:14 +00:00
debpalash c20e1c1685 fix(security): raise dependency advisory floors 2026-08-09 21:23:59 +00:00
debpalash 9a770b15d1 test(pockettts): verify pinned install on four platforms 2026-08-09 21:02:30 +00:00
dependabot[bot] b03b67ef00 chore(deps): bump aiohttp from 3.14.1 to 3.14.3
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.14.1 to 3.14.3.
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.14.1...v3.14.3)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-version: 3.14.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-09 21:01:51 +00:00
dependabot[bot] 7d6bd7af82 chore(deps): bump cryptography from 48.0.0 to 50.0.0
Bumps [cryptography](https://github.com/pyca/cryptography) from 48.0.0 to 50.0.0.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/48.0.0...50.0.0)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 50.0.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-09 21:01:50 +00:00
dependabot[bot] 70a5d69622 chore(deps): bump nltk from 3.9.4 to 3.10.0
Bumps [nltk](https://github.com/nltk/nltk) from 3.9.4 to 3.10.0.
- [Release notes](https://github.com/nltk/nltk/releases)
- [Changelog](https://github.com/nltk/nltk/blob/develop/ChangeLog)
- [Commits](https://github.com/nltk/nltk/compare/3.9.4...v3.10.0)

---
updated-dependencies:
- dependency-name: nltk
  dependency-version: 3.10.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-09 21:01:47 +00:00
dependabot[bot] f1aec13089 chore(deps): bump pypdf from 6.13.2 to 6.15.0
Bumps [pypdf](https://github.com/py-pdf/pypdf) from 6.13.2 to 6.15.0.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/6.13.2...6.15.0)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-version: 6.15.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-09 21:01:46 +00:00
Palash Debnath 46c47b68ce fix: restore generation and startup broken by the rename (#1417) (#1420)
Two bugs from the v0.4.2 rename sweep:

- The lazy model import was rewritten to `from omnivoice.models.omnivoice import VoiceStudio`, a class the library does not export. ImportError is not ModuleNotFoundError, so the #564 source fallback never caught it and /generate 500'd on every default-engine request. The class keeps its library name — it is a checkpoint-referenced identifier, not branding.
- alembic resolved a bare relative script_location against the process cwd, and the desktop shell launches the backend from frontend/src-tauri, so a pending migration killed startup. script_location and prepend_sys_path are now anchored with %(here)s, with path_separator = os so Windows drive letters and paths with spaces survive. alembic floor raised to >=1.16.

Regression tests verified fail-before/pass-after for both.
2026-08-08 02:40:52 +05:30
1cbd1c72fa fix(colab): pin torchvision==0.23.0 to resolve torchvision::nms operator missing error (#1357) (#1358)
* fix(colab): pin torchvision==0.23.0 to resolve torchvision::nms operator missing error (#1357)

This resolves the runtime import failure of transformers.HiggsAudioV2TokenizerModel due to torchvision mismatch with torch 2.8.0. Changes:

- pyproject.toml: Added torchvision>=0.19 to dependencies, pinned to 0.23.0 in constraint-dependencies, and configured the pytorch-cuda source index.

- uv.lock: Regenerated lockfile to resolve torchvision 0.23.0+cu128.

- bootstrap.rs: Added torchvision to rocm_torch_reinstall_args and updated the matching unit test.

* fix(bootstrap): pin versions in ROCm reinstall path and add CHANGELOG entry (#1358)

* test(rocm): pin bootstrap.rs to pyproject constraint, mechanically

The PR adds a "Keep in sync with [tool.uv.constraint-dependencies]" comment
above rocm_torch_reinstall_args. That is the right instruction and a
comment cannot enforce it, so it becomes a test — CLAUDE.md`s convention is
that a rule a reviewer has to remember belongs in one.

It matters more here than the usual lockstep case: an AMD user`s install
does not come from uv.lock at all. bootstrap.rs shells out to pip against
the ROCm index, so whatever it names there is the Torch stack that user
actually runs, and a drift produces no install-time error — it surfaces
later as "operator torchvision::nms does not exist" or a silent CPU
fallback, which is #972 and #1357 from two different directions.

Three cases: the constraint block still pins the trio (so the rest cannot
pass vacuously), the ROCm pins equal it, and all three are reinstalled
together — a subset leaves the others on CUDA wheels the ROCm build cannot
pair with. Both drift cases fail against the previous, unpinned form.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: debpalash <4178343+debpalash@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 16:27:36 +05:30
Palash DebnathandClaude Opus 5 b01c635bfe release: v0.4.2 (#1279)
Version files (package.json + the three mirrors) and both lockfiles bumped
0.4.1 → 0.4.2; [Unreleased] renamed to [0.4.2] — 2026-07-28.

Ships five user-facing fixes: the update toast, the restart guard that used
to discard in-flight work, the shutdown-is-not-a-crash 503, the self-healing
half-downloaded model, and the dub-history purge ordering — plus the
"Dismiss" mistranslation in five locales.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 15:56:37 -07:00
Palash Debnath 9736fd4859 release: v0.4.1 (#1239)
* release: v0.4.1

Seven user-reported issues fixed since v0.4.0 (#1221–#1229). Version bumped
across the single source of truth (frontend/package.json) and its three
toolchain mirrors; [Unreleased] renamed to the release section that
release.yml extracts verbatim as the GitHub Release body.

Docker tag examples in docs/install/docker.md and deploy/dockerhub-overview.md
updated to 0.4.1 (docs-sync rule).

* release: #1239 review — sync Cargo.lock to 0.4.1

Greptile: the manifest said 0.4.1 while Cargo.lock still recorded 0.4.0, so a
`cargo build --locked` (and the Tauri bundler's own locked build) would fail
on the mismatch. Regenerating locally updated it but it was never staged.

* release: re-sync [0.4.1] after the fix merges, date it 2026-07-27

Picks up everything merged since the section was first written: the first-run
wizard chrome (#1241), the MCP host allowlist (#1249), the macOS 12 startup
crash (#1245), and the six error-message fixes (#1247, #1251, #1254, #1256,
#1257, #1262).

Deliberately NOT included:
  - the dub delete-resurrection fix (#1252, #1253) — split to #1270 after it
    needed six rounds of correction, the last two finding that the fix did not
    close the reported case and that its own bound reintroduced it;
  - the Linux AppImage WebKit fix (#1258, #1244) — held on #1265 pending
    confirmation on a Mesa 26.1 host, which nobody has run.
2026-07-26 14:48:05 -07:00
debpalashandClaude Opus 4.8 9f6fb247ab release: v0.4.0
Bump the single source of truth (frontend/package.json) and the three
toolchain mirrors (Cargo.toml, pyproject.toml, backend/core/version.py) plus
the lockfiles (Cargo.lock, uv.lock) from 0.3.22 → 0.4.0, and rename the
CHANGELOG's [Unreleased] section to [0.4.0] with milestone highlights.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 06:46:46 +05:30
debpalashandClaude Fable 5 63fd497caf feat: TTS-only first run, platform-curated ASR, guided OS permissions, parakeet-mlx
Only the TTS model (~2.4 GB) is required on first run; ASR models are
per-platform curated picks (curated_on in models.yaml) installed on demand.
Every transcription surface returns a typed asr_model_missing error with a
one-click download CTA instead of silently pulling multi-GB Whisper weights.
Settings -> Models is a grouped, platform-aware catalog. New guided
permissions UX (wizard System Check + Settings -> Permissions + mic
pre-flight) with native mic-state checks and OS settings deep-links. New
parakeet-mlx engine brings Parakeet TDT v3 to Apple Silicon (language-gated
capture preference so multilingual dictation never regresses). Docs:
expressive-speech page, Flush/Unload + CPU-fallback triage, clone-length FAQ.
Hardening: preflight fails open for custom model pins, ROCm curation no
longer inherits NVIDIA picks, Windows mic probe reads the NonPackaged
consent key, CaptureWidget setup race fixed, offline-cache CI simulation
fixes so empty-cache runners stay green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 15:20:54 +05:30
0d4eb0f269 release: freeze v0.3.22 — version bump, lockfiles, changelog (#1150)
The dubbing release. package.json (source of truth) + the three mirrors
(Cargo.toml, pyproject.toml, version.py fallback) to 0.3.22; uv.lock +
Cargo.lock refreshed; CHANGELOG's Unreleased section (29 entries) becomes
## [0.3.22] — 2026-07-14 with the headline, split Added blocks merged.

Gates on the frozen content, all green before any version mutation:
backend 3033 + 204, frontend 1253, format, lockstep 6/6.

Co-authored-by: mergetest <nizam4103@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 03:04:17 +05:30
3aa2ef285a fix(engines): bundle en_core_web_sm — no mid-generation GitHub download (#1146)
* fix(engines): bundle en_core_web_sm — no mid-generation GitHub download

Post-merge review finding on #1144 (valid): with pip present, misaki/spaCy's
first-use auto-download WORKS now — meaning the first English MLX-Audio
generation performs a raw GitHub release download that (a) bypasses the app's
entire HF-mirror/endpoint system (restricted-network users have no recourse
mid-generation) and (b) fails offline. Local-first says default features
shouldn't spring surprise outbound requests at generation time.

en_core_web_sm-3.8.0 is now a pinned URL dependency in pyproject/uv.lock
(~12 MB wheel): it arrives at install/update time via the normal dependency
flow (where network failures are visible and retried), survives drift-sync
by construction, and spacy.util.is_package() finds it so misaki never
triggers its downloader at all. The #1143 containment stays as the backstop
for any other CLI-shaped dependency.

Also clarifies the venv test per review: pytest's interpreter IS the
uv-synced venv in CI and the packaged app, so find_spec verifies the lock;
the test now also pins the bundled model.

Validated: uv sync --frozen clean; en_core_web_sm importable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(engines): direct-URL dependency + frozen-bundle collection (review)

Two of three review P1s were real:

- Docker build break: `uv add` wrote a bare "en-core-web-sm" dependency with
  the URL only in [tool.uv.sources] — Docker's `uv pip install --system .`
  reads project metadata only, would resolve the bare name against PyPI
  (where spaCy models don't exist), and the image build fails. Now a direct
  "name @ url" dependency, the same form kittentts has always used, so every
  installer (uv sync, pip, Docker) sees the same source. Re-locked;
  uv sync --frozen clean.
- Frozen bundle: backend.spec ships mlx_audio, whose Kokoro path loads
  en_core_web_sm DYNAMICALLY (spacy.load by name) — PyInstaller never sees
  the import, so a frozen build would hit misaki's downloader at first
  English generation. collect_all('en_core_web_sm') added inside the
  mac-ARM block (plain data package, no nanobind hazard — the reason
  collect_all is banned for mlx itself doesn't apply).

Declined with precedent: "hard-coded GitHub URL breaks restricted networks"
— kittentts has shipped as exactly this GitHub-release URL form in the same
dependency list since it was added; install-time GitHub fetches are the
project's accepted pattern (the bootstrap's gh-proxy mirror exists for
restricted networks), unlike mid-generation fetches, which this PR removes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: mergetest <nizam4103@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 00:48:23 +05:30
db12b94145 fix(engines): ship pip in the managed venv — the #1133 root trigger (#1144)
The containment fix (#1143) makes a CLI-shaped dependency's sys.exit
survivable; this removes the reason it fired at all. mlx-audio's Kokoro
phonemizer (misaki) auto-downloads en_core_web_sm via spacy.cli.download,
which shells out to `python -m pip install <url>` — and uv-managed venvs
ship no pip, so the download always failed.

Why a real dependency instead of installing pip (or the model) ad-hoc at
engine load: the updater's drift sync reconciles the venv against the
lockfile (#1029/#1030, --inexact), so anything outside the lock is stripped
on the next update — the failure would quietly return after every release.
pip in pyproject/uv.lock survives sync by construction.

Validated against all lock consumers: uv sync --frozen clean; Docker's
`uv pip install --system .` reads pyproject; version-lockstep test reads
only the version field. Regression test asserts pip is importable in the
managed env.

Co-authored-by: mergetest <nizam4103@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 00:25:46 +05:30
Palash Debnathandmergetest ea7a7b39b4 feat(privacy): opt-in analytics — hardened, off by default, enforced by code (#1120)
The rejected PR #1110 had a genuinely careful PII-free event design, but shipped
three things a local-first app can't: exception autocapture ON (raw tracebacks —
home paths, and in this codebase HF tokens out of exception messages — bypassing
core.failure.sanitize() entirely), no user consent or disclosure, and 3,069 lines
of PostHog wizard scaffolding. This is the same capability with those fixed.

core/analytics.py, three rules, each enforced and tested rather than promised:

1. OFF unless the user says yes. TWO gates must both be true: a build-provided
   POSTHOG_PROJECT_TOKEN *and* the user's analytics_enabled pref, default False.
   A default install transmits nothing, so "nothing leaves your machine" stays
   literally true for everyone who doesn't opt in. A broken prefs file fails
   CLOSED. OMNIVOICE_ANALYTICS_DISABLED=1 is a hard kill switch above both.
   Withdrawing consent tears the client down immediately — no restart.

2. NO exception autocapture. Explicitly disabled; a test asserts the constructor
   arg, because the SDK's default is the leak.

3. Metadata ONLY, by allowlist. Every property passes sanitize_properties(),
   which DROPS any key not on _ALLOWED_PROPS and refuses long strings — so no
   future caller can leak a take's text, a path, or a voice name by adding a
   field. text_length is the LENGTH; the text itself has no way through.

The person id is a random per-install UUID — not hardware, hostname, or username.

UI: Settings → Privacy → "Help improve OmniVoice" states in the panel exactly
what is sent, exactly what never is, and that it can be turned off — rather than
burying it in a policy. No destination in the build (any source build) → the
toggle isn't shown, because an inert switch would be a lie.

Docs: README FAQ answers "does OmniVoice collect any data about me?" honestly.

Also fixed a bug I'd introduced in my own wiring: the generation event referenced
variables not in scope, and the call site's bare `except: pass` swallowed the
NameError — so the event would have silently never fired. The call site now logs.

12 tests (default-off / opt-in without token still can't transmit / both gates /
kill switch / consent withdrawal / prefs failure fails closed / allowlist drops
text+paths+names / long strings refused / autocapture OFF / never raises /
random install id). Backend 2936 passed; frontend 1211 passed.

Refs #1110

Co-authored-by: mergetest <nizam4103@gmail.com>
2026-07-12 18:04:07 +05:30
4d2fdacd33 release: freeze v0.3.21 — version bump, lockfiles, changelog (#1107)
package.json (single source of truth) + the three toolchain mirrors to 0.3.21;
Cargo.lock + uv.lock regenerated (version lines only). CHANGELOG [Unreleased]
renamed to [0.3.21] — 2026-07-12, "the memory release", sections merged into
house style (one Added, one Fixed).

Ships the 16 GB OOM class fixes end to end: idle-release the dictation ASR
(#1104) + one TTS engine resident at a time (#1105), plus the scoped
Settings → Storage reset/uninstall pair (#1089/#1099/#1100) and the release-
asset-split workflow fix (#1106) so this tag uploads to a single release.

test_app_version.py lockstep: 6 passed. bun install --frozen-lockfile: clean.

Co-authored-by: mergetest <nizam4103@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 15:24:07 +05:30
b0c692d26c release: freeze v0.3.20 — version bump, lockfiles, changelog (#1103)
package.json (single source of truth) + the three toolchain mirrors to 0.3.20;
Cargo.lock + uv.lock regenerated (version lines only). CHANGELOG [Unreleased]
renamed to [0.3.20] — 2026-07-12 with the release headline, sections merged into
house style (one Added, one Fixed).

Ships the #1101 stale-"ready" race fix (0.3.19 users are hitting it today), the
in-app uninstaller (#1099), and the Linux/Windows backend-log-dir fix.

test_app_version.py lockstep: 6 passed. bun install --frozen-lockfile: clean.

Co-authored-by: mergetest <nizam4103@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 14:12:47 +05:30
d7ca904a27 release: freeze v0.3.19 — version bump, lockfiles, changelog (#1096)
package.json (single source of truth) + the three toolchain mirrors
(Cargo.toml, pyproject.toml, core/version.py) to 0.3.19; Cargo.lock + uv.lock
regenerated (version lines only). CHANGELOG [Unreleased] renamed to
[0.3.19] — 2026-07-12 with the release headline; all six entries carry their
(#PR) refs and extract cleanly as the GitHub Release body.

Rebuilt on current main so the freeze covers everything that landed after the
first cut: #1088 (streaming preview), #1097 (uninstaller), #1098 (stream-drop
honesty), plus the backfilled #1088 changelog entry.

test_app_version.py lockstep: 6 passed. bun install --frozen-lockfile: clean.

Co-authored-by: mergetest <nizam4103@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 12:38:05 +05:30
2a22952f9c release: freeze v0.3.18 — version bump, lockfiles, changelog (#1084)
Co-authored-by: mergetest <test@local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 02:01:26 +05:30