Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 4, 2026, 2:24 PM ET / 18:24 UTC. Summary PR surface: Source +1009, Tests +1561, Docs +14. Total +2584 across 32 files. Reproducibility: not applicable. as a PR patch rather than a standalone bug report. The PR body provides focused unit/typing proof plus real Matrix QA run IDs for thread scenarios and live voice-STT behavior. Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Refresh the branch onto current main, inspect the exact merge result, rerun the focused Matrix tests plus Matrix voice/thread Crabbox QA, then merge only if maintainers accept the pre-mention STT and thread timeline compatibility changes. Do we have a high-confidence way to reproduce the issue? Not applicable as a PR patch rather than a standalone bug report. The PR body provides focused unit/typing proof plus real Matrix QA run IDs for thread scenarios and live voice-STT behavior. Is this the best way to solve the issue? The implementation appears to be in the right owner boundary: Matrix plugin code reuses the shared media preflight helper and matrix-js-sdk relation APIs. It is not ready to call merge-safe until the dirty branch is refreshed and maintainers accept the privacy and compatibility changes. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 17fc1c430fed. Label changesLabel justifications:
Evidence reviewedPR surface: Source +1009, Tests +1561, Docs +14. Total +2584 across 32 files. View PR surface stats
Security concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f809e2945c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const threadId = normalizeThreadId(opts.threadId); | ||
| if (threadId) { | ||
| // Thread-aware replace: Synapse needs the thread context to keep the | ||
| // edited event visible in the thread timeline. | ||
| replaceRelation["m.in_reply_to"] = { event_id: threadId }; | ||
| // Matrix keeps edit events threaded through m.new_content, not the | ||
| // outer replace relation. The outer relation must stay a pure replace. | ||
| newContent["m.relates_to"] = buildThreadRelation(threadId); | ||
| } |
There was a problem hiding this comment.
Don't rely on m.new_content for thread relations
When editMessageMatrix is called with a threadId for an original event that does not already have the thread relation, this does not make the replacement threaded: the Matrix spec's Applying m.new_content section says the original event's m.relates_to is preserved and any m.relates_to inside m.new_content is ignored. Since the outer relation here remains only m.replace, callers/tests that expect this branch to keep or add thread context will silently get an unthreaded edit unless the original event was already threaded.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in a46be7e262.
extensions/matrix/src/matrix/send.ts now keeps edit events as pure m.replace and rejects attempts to add or move thread membership. extensions/matrix/src/matrix/sdk/event-helpers.ts preserves original/wire m.relates_to when matrix-js-sdk exposes edited current content without the relation, so threaded edited events still stay out of flat reads and keep relatesTo summaries.
Verification after the fix:
node scripts/run-vitest.mjs extensions/matrix/src/matrix/sdk/event-helpers.test.ts extensions/matrix/src/matrix/send.test.ts extensions/matrix/src/matrix/actions/messages.test.tsnode scripts/run-vitest.mjs extensions/matrixnode scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfonode scripts/run-bundled-extension-oxlint.mjs.agents/skills/autoreview/scripts/autoreview --mode localclean
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a46be7e262
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if ( | ||
| !rootEvent || | ||
| rootEvent.unsigned?.redacted_because || | ||
| rootEvent.type !== EventType.RoomMessage | ||
| ) { |
There was a problem hiding this comment.
Include poll thread roots in threaded reads
When the Matrix thread root is a poll event, this early rootEvent.type !== EventType.RoomMessage return drops the starter entirely. The rest of readMatrixMessages already summarizes poll events via fetchMatrixPollMessageSummary, but relation pages never contain the root itself, so readMessages({ threadId }) for a thread started from a poll begins with replies and loses the poll question/options (and the root no longer counts toward the first-page limit). Try resolving a poll summary for the fetched root before rejecting non-m.room.message events.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 3f8dc24bc7.
extensions/matrix/src/matrix/actions/messages.ts now summarizes thread roots that are actual Matrix poll start events through the poll summary path, seeds poll dedupe with the displayed root event id, and leaves non-start poll relation events out of root summaries. extensions/matrix/src/matrix/actions/messages.test.ts covers both poll-start thread roots and poll-response thread roots.
Verification:
node scripts/run-vitest.mjs extensions/matrix/src/matrix/actions/messages.test.ts extensions/matrix/src/matrix/sdk/event-helpers.test.ts extensions/matrix/src/matrix/send.test.ts- 63 tests passednode scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo- passedoxfmt --check extensions/matrix/src/matrix/actions/messages.ts extensions/matrix/src/matrix/actions/messages.test.ts && git diff --check- passed.agents/skills/autoreview/scripts/autoreview --mode local- clean- AWS Matrix QA
run_ca858a3f1be2(provider=aws,lease=cbx_afd9f0439dab) - 12/12 passed
Co-authored-by: Frank Dierolf <frank_dierolf@web.de> Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz>
|
Land-ready after rebase onto Rebase fixes:
Local verification after rebase:
Remote/live proof already recorded in the PR body:
CI at head
Known proof gaps: none for the touched Matrix behavior; post-rebase proof reused the previously recorded live Matrix/voice-STT runs plus fresh local and CI proof. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 26e0faee20
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const reserved = roomHistoryTracker.reservePending( | ||
| _route.agentId, | ||
| roomId, | ||
| { | ||
| sender: senderId, | ||
| body: pendingHistoryText, | ||
| timestamp: eventTs ?? undefined, | ||
| messageId, | ||
| }, | ||
| historyThreadId, | ||
| ); |
There was a problem hiding this comment.
Discard deferred audio history slots on errors
When room audio preflight is deferred, this reserves a history slot and then runs the rest of continueIngress outside the room gate; if any later step throws before prepareReservedTrigger/finalizePending/discardPending runs (for example mention/config/runtime setup after transcription), the outer catch only logs and releases the inbound claim, leaving this slot permanently reserved. consumeHistory treats earlier reserved entries as gaps, so subsequent successful triggers for the same room/thread cannot advance past the stuck slot and later room history is filtered out; the deferred continuation needs a catch/finally that discards the reserved slot when it exits via an unexpected error before consumption.
Useful? React with 👍 / 👎.
* feat(matrix): handle voice preflight and threads Co-authored-by: Frank Dierolf <frank_dierolf@web.de> Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz> * test(matrix): satisfy ci guards * fix(matrix): preserve thread relations on edits * chore: annotate deprecated compatibility aliases * fix(matrix): include poll thread roots in reads * test(matrix): enable audio preflight qa config * test(matrix): make voice preflight QA mention deterministic --------- Co-authored-by: Frank Dierolf <frank_dierolf@web.de> Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz>
* feat(matrix): handle voice preflight and threads Co-authored-by: Frank Dierolf <frank_dierolf@web.de> Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz> * test(matrix): satisfy ci guards * fix(matrix): preserve thread relations on edits * chore: annotate deprecated compatibility aliases * fix(matrix): include poll thread roots in reads * test(matrix): enable audio preflight qa config * test(matrix): make voice preflight QA mention deterministic --------- Co-authored-by: Frank Dierolf <frank_dierolf@web.de> Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz>
* feat(matrix): handle voice preflight and threads Co-authored-by: Frank Dierolf <frank_dierolf@web.de> Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz> * test(matrix): satisfy ci guards * fix(matrix): preserve thread relations on edits * chore: annotate deprecated compatibility aliases * fix(matrix): include poll thread roots in reads * test(matrix): enable audio preflight qa config * test(matrix): make voice preflight QA mention deterministic --------- Co-authored-by: Frank Dierolf <frank_dierolf@web.de> Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz>
…26.6.5) (#963) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/openclaw/openclaw](https://openclaw.ai) ([source](https://github.com/openclaw/openclaw)) | patch | `2026.6.1` → `2026.6.5` | --- ### Release Notes <details> <summary>openclaw/openclaw (ghcr.io/openclaw/openclaw)</summary> ### [`v2026.6.5`](https://github.com/openclaw/openclaw/blob/HEAD/CHANGELOG.md#202665) [Compare Source](openclaw/openclaw@v2026.6.1...v2026.6.5) ##### Highlights - QQBot now strips model reasoning/thinking scaffolding before native delivery, preventing raw `<thinking>` content from leaking into channel replies. ([#​89913](openclaw/openclaw#89913), [#​90132](openclaw/openclaw#90132)) Thanks [@​openperf](https://github.com/openperf). - MCP tool results now coerce `resource_link`, `resource`, `audio`, malformed image, and future non-text/image blocks at the materialize boundary, preventing Anthropic 400s and poisoned session history after a tool returns richer MCP content. ([#​90710](openclaw/openclaw#90710), [#​90728](openclaw/openclaw#90728)) Thanks [@​RanSHammer](https://github.com/RanSHammer) and [@​849261680](https://github.com/849261680). - Anthropic extended-thinking sessions recover after prompt-cache expiry or Gateway restart because stream start events wait for `message_start`, letting pre-generation signature errors trigger the existing recovery retry. ([#​90667](openclaw/openclaw#90667), [#​90697](openclaw/openclaw#90697)) Thanks [@​openperf](https://github.com/openperf). - Parallel is now a bundled `web_search` provider with `PARALLEL_API_KEY` discovery, guarded endpoint handling, cache-safe session ids, onboarding picker support, and docs. ([#​85158](openclaw/openclaw#85158)) Thanks [@​NormallyGaussian](https://github.com/NormallyGaussian). - Google Vertex ADC users get static catalog rows and runtime model resolution again, while single-provider cooldown recovery and memory adapter status checks are more reliable. ([#​90506](openclaw/openclaw#90506), [#​90609](openclaw/openclaw#90609), [#​90717](openclaw/openclaw#90717), [#​90816](openclaw/openclaw#90816)) Thanks [@​849261680](https://github.com/849261680). - Matrix can preflight voice notes before mention gating, preserve thread reads/replies through Matrix relations pagination, and carry QA coverage for voice and thread flows. ([#​78016](openclaw/openclaw#78016), [#​90415](openclaw/openclaw#90415)) - Auth and plugin install state is more durable: auth profiles now live in SQLite, official npm plugin install records keep their trusted pins, and prerelease fallback integrity checks avoid carrying stale integrity forward. ([#​89102](openclaw/openclaw#89102), [#​88585](openclaw/openclaw#88585)) - macOS node mode no longer silently self-reconnects away from a healthy direct Gateway session, reducing unexpected companion app session churn. ([#​90668](openclaw/openclaw#90668), [#​90815](openclaw/openclaw#90815)) Thanks [@​vrurg](https://github.com/vrurg). - Upgrade and service paths are safer: cron legacy JSON stores migrate during doctor preflight, service env placeholders no longer mask state-dir secrets, WhatsApp startup waits are bounded, and disabled WhatsApp accounts tear down on config reload. ([#​90072](openclaw/openclaw#90072), [#​90208](openclaw/openclaw#90208), [#​90277](openclaw/openclaw#90277), [#​90488](openclaw/openclaw#90488), [#​90486](openclaw/openclaw#90486), [#​87951](openclaw/openclaw#87951), [#​87965](openclaw/openclaw#87965)) Thanks [@​MonkeyLeeT](https://github.com/MonkeyLeeT), [@​sallyom](https://github.com/sallyom), [@​mcaxtr](https://github.com/mcaxtr), and [@​MukundaKatta](https://github.com/MukundaKatta). ##### Changes - Search/providers: add the Parallel bundled web-search plugin, live provider tests, registration contracts, onboarding/docs wiring, and guarded `api.parallel.ai/v1/search` support. ([#​85158](openclaw/openclaw#85158)) Thanks [@​NormallyGaussian](https://github.com/NormallyGaussian). - Matrix/channels: add voice-message preflight and thread-aware read/reply behavior, including Matrix QA scenario wiring and docs for voice-message behavior. ([#​78016](openclaw/openclaw#78016), [#​90415](openclaw/openclaw#90415)) - Skills/ClawHub: install ClawHub skills backed by GitHub repositories through the resolved install API, download the pinned GitHub commit, keep install-policy checks, and report install telemetry after success. ([#​90478](openclaw/openclaw#90478)) Thanks [@​Patrick-Erichsen](https://github.com/Patrick-Erichsen). - Google Chat/channels: add native approval card actions and click handling so Google Chat approvals use platform-native cards instead of generic message flow. - Mobile: Android provider/model screens now surface expiring, unavailable, unresolved, and attention states more clearly, while iOS settings and Talk tabs keep diagnostics, gateway rows, attachment labels, and unavailable Talk controls reachable. - Memory: QMD search can use the new rerank toggle, and memory adapter status uses the resolved default model identity when checking plain status. ([#​61834](openclaw/openclaw#61834)) - Docs/tooling: add Parallel search docs, refresh weather-skill guidance toward `web_fetch`, clarify legacy `openai-codex` auth, document release/test helper scripts, and tighten changed-test routing docs for CI/debugging work. ([#​90028](openclaw/openclaw#90028), [#​90250](openclaw/openclaw#90250)) Thanks [@​fuller-stack-dev](https://github.com/fuller-stack-dev). - Release/process: switch release trains to `YYYY.M.PATCH` monthly patch numbering, keep pre-transition tags compatible, and pin the June 2026 floor at `2026.6.5` after the published beta. - Platform maintenance: refresh Android, Swift/macOS, Docker, CodeQL, Buildx, Docker build/push, and Codex Action dependencies for this release train. ([#​74980](openclaw/openclaw#74980), [#​81757](openclaw/openclaw#81757), [#​86481](openclaw/openclaw#86481), [#​86483](openclaw/openclaw#86483), [#​90601](openclaw/openclaw#90601)) - QQBot: add `/bot-group-allways on|off` slash command (with named-account and default-account support) to toggle whether group messages require an `@mention` before the bot replies, and clear the runtime config snapshot after the write so the new account-level `defaultRequireMention` takes effect immediately without restart. ([#​91423](openclaw/openclaw#91423)) Thanks [@​cxyhhhhh](https://github.com/cxyhhhhh). ##### Fixes - Channel content boundaries: QQBot now strips reasoning/thinking tags before sending, preserving final answers while hiding internal model narration from users. ([#​89913](openclaw/openclaw#89913), [#​90132](openclaw/openclaw#90132)) Thanks [@​openperf](https://github.com/openperf). - Agents/MCP/providers: coerce non-text/image MCP tool-result blocks before they reach provider converters, preserving valid images and turning richer MCP content into text instead of malformed image blocks. ([#​90710](openclaw/openclaw#90710), [#​90728](openclaw/openclaw#90728)) Thanks [@​RanSHammer](https://github.com/RanSHammer) and [@​849261680](https://github.com/849261680). - Anthropic/Codex/ACP/agent recovery: defer Anthropic stream start events until `message_start`, strip stale compaction thinking signatures before Anthropic replay, detect unsigned thinking-only stalls, refresh prompt fences after compaction writes, reject empty completion handoffs, preserve parent streaming-off overrides/shared progress commentary, forward heartbeat metadata to context-engine hooks, and cover Codex session/thread migration edge cases. ([#​90667](openclaw/openclaw#90667), [#​90697](openclaw/openclaw#90697), [#​90163](openclaw/openclaw#90163), [#​90108](openclaw/openclaw#90108), [#​89874](openclaw/openclaw#89874), [#​89505](openclaw/openclaw#89505), [#​90632](openclaw/openclaw#90632), [#​89302](openclaw/openclaw#89302), [#​90729](openclaw/openclaw#90729), [#​90317](openclaw/openclaw#90317), [#​90319](openclaw/openclaw#90319)) Thanks [@​openperf](https://github.com/openperf), [@​100yenadmin](https://github.com/100yenadmin), and [@​ooiuuii](https://github.com/ooiuuii). - Provider/model resolution: preserve Google Vertex ADC auth markers in generated catalogs, re-probe a single-provider primary after cooldown, share Codex model visibility, fail closed for unknown model auth, preserve Codex alias availability, keep unresolved profile refs unknown, and avoid resolving auth while listing models. ([#​90506](openclaw/openclaw#90506), [#​90609](openclaw/openclaw#90609), [#​90717](openclaw/openclaw#90717), [#​90702](openclaw/openclaw#90702)) Thanks [@​849261680](https://github.com/849261680). - Gateway/macOS/mobile: avoid duplicate Gateway probe warnings by identity, rate-limit node pairing requests while preserving paired-node reconnects, keep macOS node mode on a healthy direct Gateway session, keep iOS diagnostics and gateway rows reachable, and avoid Linux ARM Gradle resource tasks during Android builds. ([#​85791](openclaw/openclaw#85791), [#​90147](openclaw/openclaw#90147), [#​90668](openclaw/openclaw#90668), [#​90815](openclaw/openclaw#90815)) Thanks [@​giodl73-repo](https://github.com/giodl73-repo) and [@​vrurg](https://github.com/vrurg). - TUI/chat/Workboard/auto-reply: optimistic user messages stay stable across stale history reloads, runId reassignment, and abort windows instead of disappearing, jumping, or lingering as ghost rows; Workboard stale lifecycle bulk updates no longer overwrite newer status/provenance; message-tool sends now count as delivery. ([#​86205](openclaw/openclaw#86205), [#​89600](openclaw/openclaw#89600), [#​88592](openclaw/openclaw#88592), [#​90123](openclaw/openclaw#90123)) Thanks [@​RomneyDa](https://github.com/RomneyDa). - Cron/update/service env: doctor config preflight now migrates legacy cron JSON stores into SQLite before runtime reads, service env planning skips unresolved placeholders that would mask state-dir `.env` values, and session transcript rewrites keep registry markers/discriminants consistent. ([#​90072](openclaw/openclaw#90072), [#​90208](openclaw/openclaw#90208), [#​90277](openclaw/openclaw#90277), [#​90488](openclaw/openclaw#90488)) Thanks [@​MonkeyLeeT](https://github.com/MonkeyLeeT) and [@​sallyom](https://github.com/sallyom). - Security/config/tooling: guard MCP HTTP redirects, protect global agent config defaults, and keep release/test/tooling proof failures bounded and explicit. ([#​89732](openclaw/openclaw#89732), [#​90145](openclaw/openclaw#90145)) - Channels: WhatsApp restarts when per-account config changes, bounds background startup waits, closes failed sockets, and preserves reconnect behavior; Mattermost slash commands keep their state on `globalThis`; Feishu streaming cards preserve full merged content; voice-call tracks Twilio streams after connect; ClickClack reply tools respect `toolsAllow`. ([#​87951](openclaw/openclaw#87951), [#​87965](openclaw/openclaw#87965), [#​90486](openclaw/openclaw#90486), [#​68113](openclaw/openclaw#68113), [#​90534](openclaw/openclaw#90534), [#​90181](openclaw/openclaw#90181), [#​90607](openclaw/openclaw#90607), [#​89500](openclaw/openclaw#89500)) Thanks [@​MukundaKatta](https://github.com/MukundaKatta), [@​mcaxtr](https://github.com/mcaxtr), [@​infoanton](https://github.com/infoanton), [@​mushuiyu886](https://github.com/mushuiyu886), and [@​sahibzada-allahyar](https://github.com/sahibzada-allahyar). - Feishu: retry transient send rate-limit errors (HTTP 429, per-chat code 230020, tenant-level code 11232) with linear backoff, including SDK responses that fulfill with rate-limit bodies instead of throwing, and route streaming-card sends through the retry wrapper. ([#​89659](openclaw/openclaw#89659)) Thanks [@​ladygege](https://github.com/ladygege). - Release/CI/E2E: main CI guard drift, PR merge diff scoping, live Docker credential staging, base-image qualification, installer Docker classification, Playwright dependency install recovery, API-key auth for Codex live Docker lanes, Parallels option terminators, and JSON-mode progress handling are tighter so release proof fails cleaner. ([#​90532](openclaw/openclaw#90532), [#​90287](openclaw/openclaw#90287), [#​90058](openclaw/openclaw#90058)) Thanks [@​RomneyDa](https://github.com/RomneyDa), [@​hxy91819](https://github.com/hxy91819), and [@​mrunalp](https://github.com/mrunalp). - Release/CI/E2E: Docker E2E and live Docker harness runs now apply default memory, CPU, and process ceilings while preserving explicit per-lane overrides. - Release/CI/E2E: plugin lifecycle matrix resource sampling now fails phases that exceed RSS, wall-clock, or CPU ceilings instead of only logging the measurements. - Release/CI/E2E: Codex npm plugin live assertions now cap transcript discovery and diagnostic log reads so failure proof stays bounded. - Tests/state isolation: QA Lab valid-tool-call metrics now require runtime tool-call evidence when runtime parity data is available instead of counting tool-backed scenario pass status alone. - Tests/state isolation: QA Lab runtime parity now fails planned-only tool-call rows without matching tool results instead of treating matching mock plans as real tool evidence. - Tests/state isolation: provider, media, auth, cron, task, session, sandbox, Gateway, and Codex timeout fixtures now scope more home/state/env data per test, reducing cross-test leakage and making release validation failures less noisy. ([#​90027](openclaw/openclaw#90027), [#​89974](openclaw/openclaw#89974)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/963
Summary
Fixes #78016.
Supersedes #78069 and #71738 with maintainer-owned fixes and real Matrix QA proof.
Verification
node scripts/run-vitest.mjs extensions/matrix/src/matrix/actions/messages.test.tsnode scripts/run-vitest.mjs extensions/matrixnode scripts/run-vitest.mjs extensions/qa-matrix/src/substrate/config.test.ts extensions/qa-matrix/src/runners/contract/scenarios.test.ts extensions/matrix/src/matrix/monitor/handler.audio-preflight.test.ts- 107 tests passednode scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo- passedoxfmt --check extensions/qa-matrix/src/substrate/config.ts extensions/qa-matrix/src/substrate/config.test.ts extensions/qa-matrix/src/runners/contract/scenario-catalog.ts extensions/qa-matrix/src/runners/contract/scenarios.test.ts- passedgit diff --check- passed.agents/skills/autoreview/scripts/autoreview --mode local- cleanaws, leasecbx_afd9f0439dab, runrun_8f0cdf1afdb8,matrix-thread-follow-up,matrix-thread-root-preservation,matrix-thread-nested-reply-shape,matrix-thread-isolation,matrix-room-thread-reply-override,matrix-dm-thread-reply-override, suite9/9aws, leasecbx_21488e75b770, runrun_f9edb5fe2a5f,matrix-voice-preflight-mention, provider modelive-frontier, suite4/4