## Problem
`earshot` is our huddle VAD. `desktop/src-tauri/Cargo.toml:143` declares
`earshot = "1.0"` — a caret range — so **only the lockfile** holds us at
1.1.0. `renovate.json` has `automerge: true` with `postUpdateOptions:
["cargo:updateLockfile"]`, and exempts only *major* bumps from
automerge. 1.2.2 published 2026-08-19 and satisfies the range, so it is
eligible on Renovate's next run.
That bump is not safe to take on its own. It is a **quantized
re-implementation, not a tuning release**: `weights.bin` goes 77,124 →
39,940 bytes, the RNN weights move `f32` → `i16`, the mel filterbank
offsets are rebuilt, and `sqrtf` is replaced with a fast `rsqrtf`. Same
crate name, different network — and the probability scale moves with it
(1.1.0 never exceeds 0.935 and puts 1.0% of frames above 0.9; 1.2.2
reaches 0.9909 with 35.4% above 0.9).
Measured on a matched 121-clip corpus (11 Pocket TTS voices × 11
conditions, 38,254 scored frames), at our shipped threshold:
| metric | 1.1.0 | 1.2.2 |
|---|---|---|
| TPR | 89.57% | **88.46%** |
| FPR | 1.54% | **2.79%** |
| CPU / frame | 6,550–6,777 ns | **3,841–3,978 ns** |
AUC does improve (+0.0045 all-conditions) and CPU is a genuine 1.70x
win, so the bump is worth taking — but the AUC gain is in an ROC region
we do not operate in, and the FPR-matched threshold for 1.2.2 is ~0.574,
not 0.5. It needs a threshold re-pick, not a lockfile bump.
The risk is the shape of the diff. The last earshot bump — #654, "update
rust crate earshot to v1.1.0" — was lockfile-only (+23/−26, one file)
and went from opened to merged in **15 minutes**. That is the correct
instinct for a lockfile bump and exactly wrong here: two lines in
`Cargo.lock` would silently re-tune the VAD.
## Fix
One `packageRules` entry pinning earshot below 1.2.0, following the
existing `evalexpr` and `@tiptap/*` pin pattern in the same file. The
rationale lives in the `description` field so the next person to hit the
pin sees why.
A source comment cannot prevent this, because Renovate does not read
comments. This is the mechanical guard.
## Verification
- `renovate.json` parses; the new entry's key set matches the two
existing `allowedVersions` pins.
- Range semantics checked: 1.0.0 / 1.1.0 / 1.1.9 allowed; 1.2.0 / 1.2.1
/ 1.2.2 / 2.0.0 blocked.
- All eight pre-push gates green (branch-skew, file-size, desktop
check/typecheck/test, mobile, rust-tests, desktop-tauri-checks).
- I could **not** run `renovate-config-validator` — the npm registry is
unreachable from this host (`ECONNRESET` via the Artifactory mirror).
The checks above are a structural and semantic substitute, not a
substitute for the official validator.
## Scope
Config-only. No behavior change, no code touched. Unblocking is a
deliberate follow-up: take 1.2.2 together with a threshold re-pick
against the same corpus, which is already parked in the Silero bake-off
arc.
Measurement details and the harness are in my workspace at
`RESEARCH/EARSHOT_1_1_0_TO_1_2_2_MEASUREMENT_2026_08_20.md` (not in this
repo).
Signed-off-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz>
Signed-off-by: Tyler <tlongwell@block.xyz>
Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz>
Co-authored-by: Tyler <tlongwell@block.xyz>
Configure Renovate to wait three days before proposing newly released
dependencies.
The policy requires a registry publication timestamp and suppresses
branches until the release ages past the window. Renovate security-alert
updates continue to bypass minimum-release-age checks, so known fixes
are not delayed.
Checked with `renovate-config-validator --strict --no-global
renovate.json`, `jq`, and `git diff --check`.
Signed-off-by: Jordan Mecom <jm@squareup.com>