`ensureMatrixSdkInstalled` previously derived an install `cwd` via fixed
two-segment traversal from `import.meta.url` and spawned `npm install`
(or `pnpm install`) when Matrix packages were missing. Under the
externalized plugin layout the derived path is a scope directory like
`<config>/npm/node_modules/@openclaw`, so npm walks up to the managed
project root and prunes undeclared siblings. Under the legacy bundled
layout it would target `<global-prefix>/lib/node_modules` and could
delete unrelated global CLIs.
Matrix is now a pure availability check: if any required package fails
to resolve, it throws an actionable error pointing the operator at the
supported repair commands (`openclaw plugins update matrix`,
`openclaw doctor --fix`). This matches extensions/AGENTS.md:
"Runtime never installs deps; install/update/doctor are repair points."
The exported signature stays backwards-compatible (all params optional;
`confirm` and `runtime` are accepted but ignored). `resolveMissingMatrixPackages`
gains an optional `resolveFn` seam for testability, mirroring the existing
`ensureMatrixCryptoRuntime` injection pattern.
Fixes#80758.
Matrix outbound markdown was hitting the shared `resolveMarkdownTableMode`
"code" fallback for every send because the Matrix channel plugin never
declared `defaultMarkdownTableMode` in its `messaging` block at
`extensions/matrix/src/channel.ts:452`. Tables were emitted as
`<pre><code>` fenced blocks across every Matrix client.
This change declares `defaultMarkdownTableMode: "bullets"`, matching the
Signal and WhatsApp precedent at `extensions/signal/src/shared.ts:111`
and `extensions/whatsapp/src/shared.ts:261`. The choice matches the
cross-client compatibility profile the issue filer surveyed:
Element X iOS squashes HTML `<table>` and Element X Android drops cell
text entirely (element-hq/element-x-android#1551), while bullet lists
render cleanly across every Matrix client. Operators wanting the
previous fenced-code rendering can set `channels.matrix.markdown.tables:
"code"` explicitly; clients that do render real tables can opt in with
`channels.matrix.markdown.tables: "off"` (markdown-it's `table` rule is
already enabled by default through the markdown-it default preset, so
raw markdown tables flow through to native HTML tables on that path).
Docs and the changelog entry list Matrix alongside Signal and WhatsApp
as a bullet-default channel.
Fixes#78990.