Run #1861 built fine but `npm publish` refused: "You must specify a tag
using --tag when publishing a prerelease version" (npm 11 rule). Add
`--tag lotus`; cinny pins exact versions so the dist-tag is only a
namespace.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
Run #1859: install, tsc, oxlint, knip and oxfmt all passed; the unit
suite then failed 1/648 — DeveloperSettingsTab's snapshot expects the
version to read "dev" when VITE_APP_VERSION is unset, but the workflow
exported it (= "lotus") at workflow level, so it leaked into the tests.
Set it on the two build steps only, which is the only place it matters.
Reproduced locally: the test fails with the variable set and passes
without it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
Run #1855: `npm install -g pnpm@…` failed with EEXIST because the runner's
persistent hostedtoolcache Node install still carries the corepack `pnpm`
shim from earlier `corepack enable` runs, and npm won't overwrite it.
Disable/remove the shim first, then install, and print the version so the
log shows which pnpm actually ran.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
Run #1854 failed in `pnpm install --frozen-lockfile`: matrix-js-sdk is a
git dependency (upstream pins matrix-org/matrix-js-sdk#develop) that pnpm
must build from source, and that source's devEngines pins pnpm 11.9.0.
Under `corepack enable` the nested `pnpm install` runs the 11.21.0 shim,
which refuses to switch versions ("pnpm does not switch versions when
running under corepack") and the prepare step aborts. Reproduced locally
with a fresh store; with a real pnpm binary the nested install downloads
11.9.0 itself and succeeds.
Both jobs now `npm install -g pnpm@<version>` with the version read from
package.json's packageManager field.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
The workflow only built and smoke-checked that dist/index.html existed,
so a type error, lint violation or failing test could be tagged straight
to a published npm release. Run `pnpm lint` (tsc + oxlint + knip),
`pnpm format:check` (oxfmt) and `pnpm test:unit --run` before the build,
all hard. Add the same cancel-in-progress concurrency group cinny's CI
uses so rapid pushes to lotus don't queue redundant full builds.
Also fixes the one tsc error the v0.25.0 merge surfaced in
lotusDecorations (lazyActions.off now returns the emitter), so the new
gate is green from its first run.
Fixes#5Fixes#34
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
Merge upstream element-hq/element-call tag v0.25.0 into the Lotus fork
(previous base: v0.20.1; actual merge-base v0.20.1-rc.1). Every Lotus
feature and all six io.lotus.* widget actions are preserved. Version
bumped to 0.25.0-lotus.1.
Conflict files and how each Lotus hunk was re-expressed:
* src/state/CallViewModel/remoteMembers/ConnectionFactory.ts
Upstream moved echoCancellation/noiseSuppression/autoGainControl from
constructor params (fed by URL params) to persisted Settings
(settings.ts) with a developer-settings UI. The cinny host still drives
these per call via URL params (noiseSuppression=false /
autoGainControl=false when the in-source ML denoiser is active, so the
model gets a raw mic) - taking upstream verbatim would silently break
the ML denoise tier. Re-wired as AND semantics in generateRoomOption():
a constraint is enabled only if BOTH the Setting and the URL param
allow it. Params default to true, so with no params this is
byte-for-byte upstream behaviour. Upstream's own echoCancellation /
noiseSuppression URL params (still parsed but dead in v0.25.0) work
again as a side effect. Lotus autoGainControl URL param kept in
UrlParams.ts (auto-merged, unchanged).
* src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts
Took upstream (tests now drive via Settings). The lost Lotus coverage
is restored in a NEW colocated file src/lotus/lotusAudioConstraints.test.ts
(3 tests) so the upstream test file stays pristine. Verified the new
test fails against pure-upstream ConnectionFactory and passes with the
re-wiring.
* src/state/CallViewModel/CallViewModel.ts
Three small hunks: kept both the Lotus `userMedia$` interface member
and upstream's new `keyRotationSuppressed$`; dropped the three Lotus
audio constructor args (mechanism removed upstream, see above); kept
both in the returned object. The [lotus #4] overrideSpotlight$ routing,
manualSpotlightUserId$ and setManualSpotlight auto-merged; verified
against upstream's changed ringingMedia$ (now single-or-null instead
of array) - the merge correctly took upstream's outer branch and the
inner screenShares$/spotlightSpeaker$ logic that lotusSpotlight.ts
mirrors is unchanged upstream.
* src/index.css
Kept both: Lotus lotus-transparent / lotus-theme blocks and upstream's
new body[data-background="gradient"]::before full-viewport gradient.
The naive merge swallowed the closing brace of body.lotus-theme -
restored. Added a rule hiding the new gradient pseudo-element under
body.lotus-transparent, since it would otherwise paint over the
transparent body and hide the host wallpaper.
* src/components/CallFooterViewModel.tsx, src/components/CallFooter.stories.tsx
No Lotus content - pure upstream-vs-upstream conflicts caused by the
merge base being v0.20.1-rc.1. Took upstream (layoutMode ->
layoutSwitchVm; setLayoutMode removed). No Lotus code uses
setGridMode/layoutMode.
Non-conflicting but reviewed:
* src/widget.ts auto-merged cleanly. Upstream's removal of .well-known
transport advertisement and the new RTC-transport capability request
did not touch the action registration loop the LOTUS_TO_WIDGET_ACTIONS
spread and widget.lazyActions ride on - nothing to re-wire.
* src/room/InCallView.tsx, src/useAudioContext.tsx, src/useTheme.ts,
src/tile/MediaView.tsx(+.module.css), src/UrlParams.ts(+test),
all *.module.css and .gitea/workflows/ci.yml auto-merged; each diff
against v0.25.0 was checked to equal the original Lotus hunk.
* src/button/Button.module.css: the merge appended an exact duplicate
of upstream's `.rotate`/`@keyframes spin` block (rc.1 merge-base
artefact) - reset to upstream verbatim.
* src/grid/OneOnOnePortraitLayout.module.css was renamed upstream to
OneOnOneMobileLayout.module.css; git followed the rename and the Lotus
safe-area PiP inset fix applies there (the --content-inset-* vars it
uses still exist upstream).
Tooling changes inherited from upstream that affect the fork:
* eslint + prettier were replaced by oxlint + oxfmt (`pnpm lint:oxlint`,
`pnpm format:check`). oxlint flagged 10 issues, all in src/lotus/*:
8x no-meaningless-void-operator (dropped the `void` before void-typed
widget transport.reply / callbacks - no behaviour change), 1x
consistent-type-imports (lotusWidget.ts: `import type`), and 2x
unicorn/no-useless-spread in lotusAudioInject.ts which are FALSE
POSITIVES - `[...activeClips]` is a required defensive copy because
abort() deletes from the Set during iteration; suppressed with an
explanatory eslint-disable-next-line. oxfmt reformatted 7 Lotus
touched files (whitespace only).
* packageManager bumped by upstream to pnpm@11.21.0, which requires
Node >= 22.13 (uses node:sqlite). Node 20 cannot run it; pnpm 10.33
cannot read the new lockfile either (matrix-js-sdk is now a git
dependency on develop, using a version-union pnpm 10 rejects). Fork CI
already uses Node 24 (.node-version), so CI is unaffected.
* matrix-js-sdk is now github:matrix-org/matrix-js-sdk#develop (pinned
by commit in pnpm-lock.yaml).
Lotus behaviour NOT preserved: none found.
Verification (Node 24.11.1, pnpm 11.21.0): pnpm install --frozen-lockfile
OK (lockfile taken from upstream unchanged, no regeneration needed);
tsc clean; oxlint clean; oxfmt --check clean; knip exit 0 (2 config
hints in upstream knip.ts only); vitest unit 84 files / 627 passed /
9 skipped; build:embedded OK, staged to embedded/web/dist (44M), all
six io.lotus.* action strings present in the bundle.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
The in-source ML denoiser is gated on lotusDenoiseSource (see lotusDenoise.ts
gate), not the legacy build-time shim flag lotusDenoise=ml. Correct the two
stale references (lotusDenoise.ts JSDoc + InCallView.tsx comment) to
lotusDenoiseSource=1.
Bump the embedded package to 0.20.1-lotus.2 for the next publish and update the
CI comment: the checked-in version now tracks the intended release, while a
pushed tag still wins (npm version "$TAG" overwrites at publish time).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
upload-artifact@v4 needs GitHub's artifact backend, which the Gitea
act_runner doesn't implement — it failed the build job with exit 1 even
though build:embedded + smoke-check passed. The publish job rebuilds from
source, so the artifact was only a convenience.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
build:embedded outputs to repo-root dist/; the publish job and smoke-check
expected embedded/web/dist (the publish template's files entry), which was
never created in CI — so a tagged publish would fail its smoke-check or ship
an empty tarball. Copy dist -> embedded/web/dist in both jobs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- embedded/web/package.json: publish as @lotusguild/element-call-embedded
from our Gitea fork (repository URL updated).
- .gitea/workflows/ci.yml: build the embedded bundle on PR/push to lotus;
publish to the Gitea npm registry on a v* tag. Linux-only (web bundle).
Based on upstream element-call v0.20.1 (2d74c48).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>