- N124: denoise shim cleanup() now disconnects the noise gate AudioWorkletNode
(var-scoped, guarded), releasing the gate processor thread instead of leaking
it on every getUserMedia within a session.
- N125: denoise-status postMessage now targets the parent origin (derived from
the parentUrl widget param via new URL(...).origin, falling back to this
frame's origin) instead of broadcasting with '*'.
- N128: patch-folds.mjs fails hard (process.exit(1)) when the patch target is
missing, so an unpatched folds can't silently ship. The idempotent
"already applied" path still exits 0 (verified by re-run).
- N120: the avatar-decoration CDN URL is now single-sourced in
avatarDecorations.ts (DECORATION_CDN); syncDecorations.mjs extracts it by
regex (can't import across the build/app boundary) and fails hard if renamed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prettier: auto-formatted 103 files to fix baseline. Prettier check in CI
is now a hard gate (removed continue-on-error).
Brotli: installed libnginx-mod-http-brotli-filter/static. Enabled in nginx
with brotli_static on for pre-compressed assets and comp_level 6.
Sentry releases: deploy script now exports VITE_APP_VERSION=<git-short-sha>
before building so each Sentry release maps to an exact commit.
CI also passes github.sha as VITE_APP_VERSION.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add defensive check in folds Icon component so that if src is ever
undefined or non-function (root cause unknown, possibly data-dependent),
the SVG renders empty rather than throwing and crashing the whole app.
Also adds postinstall script to re-apply the patch after npm install.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>