* refactor: resolve oxlint correctness findings without behavior changes
- Snapshot iterations that mutate their collection with Array.from()
instead of a spread (live childNodes, self-removing disposers, a Set
extended inside its own loop).
- Drop empty spread fallbacks, redundant regex escapes, Boolean() casts
inside negations, a rethrow-only try/catch and statement ternaries.
- Use startsWith/endsWith for anchored literal checks in the extension.
- List U+FE0F explicitly in the mobile attachment emoji class; the
matched set is unchanged.
- Fix the WeChat copy fixture, where \oint in a template literal lost its
backslash and the block formula never exercised \oint.
- Document the intentional control-character regexes (filename
sanitizing and input validation), the throwing provider stream test,
Astro's generated type reference and the mobile auto-sync finally
block with narrow inline exceptions.
* ci: run oxlint correctness rules on pull requests
Pin oxlint 1.88.0 and enable only its correctness category across apps/
and packages/, excluding build output, vendored code and the iOS app.
Findings are errors and the script passes --deny-warnings, so CI fails
on any finding. no-unused-vars stays off until unused code is removed
in a dedicated pass.
The full non-E2E suite (`bun run test`) only ran inside the release
workflow, and pull requests only built the Docker image, so a failing test
or type error surfaced at release time. A new Test workflow runs on every
pull request and push to main (Markdown and docs-only changes excluded):
- "Type check and build": `bun run typecheck`, `bun run typecheck:mobile`
and `bun run build:web`;
- "Regression tests": `bun run test` (bulk and integration suites).
It uses the Bun version pinned in package.json, retries `bun install` like
the other workflows, cancels superseded runs, reads the repository only,
and is limited to this repository so deployment forks spend no runners.