Commit Graph
16 Commits
Author SHA1 Message Date
Thore CimbalandClaude Opus 4.8 dcc86431dc fix(audio): restore the upstream off-path, gate the AI filter off (v0.5.0 incident)
threadnet.8 broke unmuting in production, both ways. With the filter on, LiveKit
refuses the processor because the room is built without webAudioMix, so no local
track ever carries an AudioContext. With the filter off, the options builder
still emitted processor: undefined and rewrote noiseSuppression - LiveKit copies
every key of audioCaptureDefaults into the getUserMedia constraints, undefined
included, and Safari stopped unmuting over it.

The off-path is now a conditional spread that produces an object identical to
upstream: no processor key at all, noiseSuppression untouched. Two regression
tests pin this down and were demonstrably red on the old code.

The feature itself is hard-gated off (AI_NOISE_SUPPRESSION_AVAILABLE) until the
webAudioMix decision is made and tested in a two-person call. The gate also
neutralizes clients that enabled the setting before - that state lives in
localStorage and survives every deployment. The settings UI hides behind the
same gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-16 12:00:00 +00:00
Thore CimbalandClaude Opus 4.8 d270e0c706 fix(embedded): ship the model assets in the widget package
Element Call reaches production only as the embedded npm package, which webpack
copies into ThreadNet-Web under /widgets/element-call/. The embedded build sets
publicDir: false — upstream reasons that public/ holds nothing but the favicon,
which stopped being true when the model assets landed there.

Verified rather than assumed: with the upstream value everything builds, the
standalone bundle works, and the filter is dead only inside the widget, 404ing on
the model. That is the failure this would have shipped.

The package grows from about 41 to 66 MB, measured — most of what was already
there is source maps and the crypto and vision wasm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-16 12:00:00 +00:00
Thore CimbalandClaude Opus 4.8 3f17001720 feat(audio): opt-in AI noise suppression against keyboard noise
The WebRTC noise suppression estimates a running noise profile, so it removes
stationary noise but not keystrokes, which are transient and never look like
noise to it. Chiclet keyboards are as affected as mechanical ones. DeepFilterNet3
runs client-side as a LiveKit track processor and removes them.

Off by default and the model is only fetched once a user switches it on, so
nobody pays the download who does not want the filter. Default strength is 35
percent rather than full: measured, that already gives keystrokes gone with the
voice still natural, and more attenuation only adds artefact risk.

Assets ship with us instead of the package's default CDN, which would report
every participant's IP to a third party at call start and tie call setup to
foreign infrastructure. The Dockerfile gzips the model wasm, which the existing
top-level glob missed — 4.1 MB instead of 15.7 MB per client.

Browser noise suppression is switched off while the filter runs so the two do not
work against each other. Regulation goes through the model's own attenuation
limit, so there is no dry/wet mixer and no delay compensation to get wrong.

Decision and measurements: management ADR-0018 and issue #0054.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 12:00:00 +00:00
Thore CimbalandClaude Opus 4.8 c63be9ab94 docs: add group-rules pointer (CLAUDE.md) and repo-specific AGENTS.md
Field test F-011 found four of five components carried no pointer file, so a
session landing here had no path to the group rules at all. CLAUDE.md is the
one-line pointer the check looks for; AGENTS.md links the canonical rules in the
management repo (with the Gitea mirror URL for readers outside the lab) and
otherwise carries only what is specific and easy to get wrong here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-15 12:00:00 +00:00
Thore Cimbal d13cce7337 docs: describe the automated publish, not the manual process it replaced
Section 4 still described a manual/local npm publish with an untracked .npmrc - obsolete since publish_npm landed in .gitlab-ci.yml on 2026-08-06. Documents the actual job: manual trigger, GITEA_NPM_TOKEN, the empty-package guard, and the threadnet dist-tag.
2026-08-09 12:00:00 +00:00
Thore Cimbal 3675cab385 ci: stamp the widget build with its version
Without VITE_APP_VERSION the bundle calls itself dev - in developer settings and in every error message. Someone reporting a call problem then cannot say which build they were on.

Set to the package version plus the short commit: the first says what was published, the second what was actually built. Between two publishes only the latter changes, and then it is the only thing that tells two builds apart.

Closes axion1337.chat/threadnet-call#3
2026-08-09 12:00:00 +00:00
Thore Cimbal dc2a041b83 docs: repoint commit references after the history rewrite
The anonymisation rewrite of 2026-08-07 gave every touched commit a new SHA, leaving the references in these documents pointing at objects that no longer exist. The mapping was reconstructed from the backup branches and each pair verified by tree and commit message before substituting.

Prefix lookups were built for lengths 7 to 12 and any ambiguous prefix would have been skipped; none were ambiguous across all 251 pairs.
2026-08-09 12:00:00 +00:00
Thore Cimbal e793902ae0 ci: do not create a pipeline for docs-only commits
Same trap as in ThreadNet-Web: a commit touching only docs/ produced a pipeline with zero jobs, which GitLab marks as failed - pipeline 187 on 2026-08-06. build_embedded is skipped by its changes rule and publish_npm depends on it, so nothing is left.

The path list is now a YAML anchor shared with build_embedded instead of a second copy. CI_PIPELINE_SOURCE == web stays allowed so publish_npm remains reachable after a docs-only commit.

Refs axion1337.chat/threadnet-call#1
2026-08-07 12:00:00 +00:00
Thore Cimbal 846135e48d embedded: 0.19.2-threadnet.7 + Schutz gegen leere Pakete
0.19.2-threadnet.6 liegt mit 12,5 KB statt 12,8 MB in der Registry: package.json und Lizenzen, kein dist/. Woher der Upload kam, laesst sich nicht mehr klaeren - beide publish_npm-Laeufe von heute sind fehlgeschlagen, der eine vor dem Upload am fehlenden dist-tag, der andere danach mit 409. Die Nummer ist verbrannt, npm-Versionen sind nicht ueberschreibbar.

Der neue Check bricht ab, wenn embedded/web/dist weniger als 50 Dateien hat (erwartet ~150). Das kostet nichts und verhindert, dass diese Klasse Fehler noch einmal eine Versionsnummer verbrennt.
2026-08-06 12:00:00 +00:00
Thore Cimbal 6f94e6a8a3 CI: dist-tag beim npm-Publish setzen
npm bricht ab, sobald eine Version wie 0.19.2-threadnet.6 ohne --tag veroeffentlicht werden soll - der Suffix macht sie zur Prerelease. "threadnet" statt "latest", denn latest soll nicht auf eine Vorabversion zeigen.

Refs axion1337.chat/threadnet-call#2
2026-08-06 12:00:00 +00:00
Thore Cimbal 84419133b3 embedded: 0.19.2-threadnet.6 - Widget heisst jetzt aXion1337.Chat
Erste Version mit VITE_PRODUCT_NAME. Am Artefakt von Pipeline 189 verifiziert.

Refs axion1337.chat/threadnet-call#2
2026-08-06 12:00:00 +00:00
Thore Cimbal 3f0f55e6bd Doku: Logo-Inventur korrigieren und Verifikation nachtragen
Meine erste Aussage "Logo.svg und LogoLarge.svg sind unreferenziert" war falsch - der Grep hatte icons/ herausgefiltert. Alle vier Logo-SVGs sind importiert und im Bundle; gerendert wird im Widget trotzdem keins, jeweils durch dieselbe HeaderStyle.Standard-Bedingung gesperrt. Das ist der belastbarere Befund, weil er an der Render-Bedingung haengt statt an einem Suchtreffer.

Refs axion1337.chat/threadnet-call#2
2026-08-06 12:00:00 +00:00
Thore Cimbal ac688d36f7 CI: Build-Output an die Stelle legen, an der das npm-Paket ihn erwartet
build_embedded sammelte embedded/web/dist, Vite schreibt aber nach dist/ - der Job lief seit jeher gruen und lud dabei NICHTS hoch ("WARNING: embedded/web/dist: no matching files"). publish_npm haengt per needs:artifacts daran und haette ein Paket ohne dist/ veroeffentlicht.

Upstream setzt den Pfad ueber das Download-Ziel des Artefakts; hier wird nach dem Build verschoben.

Refs axion1337.chat/threadnet-call#2
2026-08-06 12:00:00 +00:00
Thore Cimbal a6e555ac3f CI: .env.production als Build-Trigger aufnehmen
Die Datei setzt VITE_PRODUCT_NAME und landet damit im Bundle, stand aber nicht in der changes:-Liste von build_embedded - der vorige Commit haette also den Produktnamen geaendert, ohne dass die CI ueberhaupt baut.

Refs axion1337.chat/threadnet-call#2
2026-08-06 12:00:00 +00:00
Thore Cimbal 0823c8a866 Produktname im Widget: aXion1337.Chat statt Element Call
VITE_PRODUCT_NAME ist upstream bereits an jeder Stelle vorgesehen (import.meta.env.VITE_PRODUCT_NAME || "Element Call"). Sie in .env.production zu setzen benennt das Widget vollstaendig um, ohne eine einzige Quelldatei anzufassen - also ohne Merge-Reibung beim naechsten Upstream-Update.

Die Inventur in docs/axion1337-fork.md haelt fest, was dadurch tatsaechlich umbenannt wird und was im Embedded-Build ohnehin nie erscheint: die Logo-SVGs rendern nur bei HeaderStyle.Standard, dem Nicht-Widget-Default; Startseite und Login gibt es nur standalone. Die deutschen matrixRTCMode-Beschreibungen bleiben bewusst stehen - sie reden ueber fremde Gegenstellen, nicht ueber uns.

Refs axion1337.chat/threadnet-call#2
2026-08-06 12:00:00 +00:00
Thore CimbalandClaude Fable 5 8fb630cfb3 ci: GitLab-Pipeline - build_embedded + manueller npm-Publish nach rohana (threadnet-call#1)
Registry-Entscheidung evidenzbasiert: das Package ist pnpm-Dependency von
ThreadNet-Webs apps/web, der Lockfile pinnt die Tarball-URL auf rohana -
Registry bleibt dort. Publish-Auth ueber CI-Variable GITEA_NPM_TOKEN statt
lokaler Klartext-.npmrc.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 12:00:00 +00:00