# v2.21.0 — the things that were reported as working and were not

**Released 2026-08-15.** Upgrade:

```sh
sudo snap refresh yazses     # snap
pipx upgrade yazses          # or: uv tool upgrade yazses
```

Sixty-nine commits had built up behind v2.20.0. Read back across them, they share a
theme worth naming: almost every one is a thing that *reported success* and was not
succeeding. A green check mark, a passing guard, a tray icon, an "Update installed"
message — each of them true-looking and wrong.

That is a harder failure than a crash, because nothing asks to be looked at.

## Guards that passed by checking nothing

Three packaging guards iterated a collection and asserted on each element. The
collection was empty. A `for` loop over nothing raises no error and reports success, so
all three had been green since the day the files they globbed moved — proving, in
effect, that no rule was broken because no rule was checked.

The same shape turned up twice more: the CLI-reference guard read **58** command names
and never opened a command *group*, leaving roughly **50** subcommands unchecked
(`TyperGroup` is not a `click.Group` under Click 8.4, so an `isinstance` walk finds
nothing and passes), and **eleven** tests behind an optional extra were skipped in every
CI job — a skip is not a failure, so nothing ever said so.

There is now a test that fails when a guard would pass on an empty set, which makes the
class of bug mechanical rather than a thing to remember.

## A crashed daemon stayed dead on Windows and macOS

Linux had `Restart=on-failure` through its systemd user unit. Windows and macOS had
nothing: if the daemon died, it stayed dead, dictation silently stopped working, and the
tray icon — which polls the daemon — went on being drawn. The supervisor now re-checks
liveness from the tray lock and relaunches, bounded at five attempts.

## `yazses features` now says what a capability costs

The catalogue listed 145 capabilities and the price of none of them. The number existed
— `features enable` has printed it since ADR-018 — but only once the download had
started, which is after the decision rather than before it.

```console
$ yazses features
│  ○ off  Cocktail Filter (voice focus)    cocktail         ~3.1 GB   experimental
│  ○ off  Glance-Type (camera)             gaze             ~219 MB   experimental
│  ○ off  Dictation Reflow                 reflow                     optional
```

Three capabilities resolve to ~3.1 GB apiece, because `speechbrain` pulls PyTorch and
the CUDA stack behind a name that reads like a small audio filter. A blank cell means
nothing to download, which is true of most of them.

New guide: **[Install only what you need](../how-to/install-only-what-you-need.md)**.

## Also in this release

- **The Command Safety Gate is wired** — a misheard `rm -rf` now waits for a spoken
  *confirm* instead of being typed.
- **Check digits on dictated numbers** — a card or ISBN whose check digit fails is held
  rather than typed, through the same confirm gate, so there is one release phrase to
  learn rather than one per guard.
- **The tray shows whether the microphone is hearing you** — a live input-level ring
  with a notch at the silence gate. The five state colours all say what YazSes is
  *doing*; none said whether audio was arriving, and those come apart exactly when it
  matters.
- **An Intel macOS build**, and `.dmg` filenames that name their architecture.
- **Settings-window secondary text now passes WCAG AA** — it was `#808080`, which
  measures 3.43:1 on Qt's light theme and 3.44:1 on its dark one, against the 4.5:1 AA
  requires. It failed on both.
- **Windows installs are no longer told to update with `pip`** — choco, winget and
  scoop each get the command that actually works for them.
- **An opt-in release check** (off by default) that tells you once when a new version
  lands.
- **Streaming transcription is measured as a loss** on every model but `tiny.en`, and
  `features enable` now says so instead of recommending it.

## Fixed

- A CI job that could only ever be red, for weeks.
- `uv.lock` still recorded the project as 2.18.2 after two releases had shipped.
- PyPI was told YazSes supports two Python versions; CI proves four.
- The benchmarks page told readers to run a harness that was not in the repository.
- The Flathub listing had no screenshots, and nothing in the repo read that file.
- "Update installed" was reported for upgrades that never happened — `uv tool upgrade`
  exits 0 on a pinned install.

The full list is in the [changelog](https://github.com/MSKazemi/yazses/blob/main/CHANGELOG.md).
