lotus(#1): fix restart-silence (A7), 48kHz ctx; protocol + CI hardening
CI / Build embedded bundle (push) Successful in 1m20s
CI / Publish to Gitea npm registry (push) Has been skipped

Denoise deep-review (CRITICAL): restart() read opts.audioContext, which
LiveKit does NOT pass on restart — so reconnect (the A7 scenario) and mic
device-switch threw after stopping the old track, leaving the mic SILENT
(A7 reintroduced). Fix:
- Processor owns a dedicated 48kHz AudioContext (sapphi worklets require
  48kHz; H1), reused across restart, closed on destroy.
- restart() never throws and never leaves a stopped track on the sender:
  builds the new graph first, then disposes the old; on failure degrades
  to RAW mic audio rather than silence.
- Cache wasm per URL (no re-fetch each reconnect); gate threshold default
  -45 and accept an explicit 0 (M2); document the cross-repo asset contract.

Protocol audit:
- Non-silent warning when an unsupported denoise model (dtln/deepfilternet)
  is requested instead of silent rnnoise fallback (F3).
- Correct the call_state enum comment (immediate error-reply, not 10s) (F2).

Build/CI audit:
- Stamp VITE_APP_VERSION in CI; document the vX.Y.Z-lotus.N version scheme.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Lotus CI
2026-06-30 00:15:59 -04:00
co-authored by Claude Opus 4.8
parent b8543c3fe1
commit 29592fbb18
4 changed files with 116 additions and 37 deletions
+5 -3
View File
@@ -14,9 +14,11 @@ export enum LotusWidgetActions {
/**
* fromWidget: in-call per-participant speaking / mute state.
* NOTE: matrix-widget-api `transport.send` is request/response — the host
* MUST reply/ack each one (cinny's `listenAction` does, replying `{}`),
* otherwise every send sits pending for the 10s transport timeout and then
* rejects, producing continuous churn + log noise for the whole call.
* MUST register a handler that replies/acks each one (cinny's `listenAction`
* does, replying `{}`). If the host has no handler, ClientWidgetApi
* immediately error-replies "unsupported from-widget action", so the data is
* silently dropped and each throttled send rejects (caught) — functional miss
* + log churn, not a hang.
*/
CallState = "io.lotus.call_state",
/** toWidget: pin/spotlight (or clear, with userId=null) a participant. */