* chore(release): close out 2026.6.10 on main
* chore(release): align native app metadata for 2026.6.10
* chore(release): sync Android 2026.6.10 notes
* docs(changelog): preserve 2026.6.9 history
* docs(changelog): preserve 2026.6.9 history
Move Canvas, Discord, Slack, voice-call, and WhatsApp skill docs from the root bundled skill tree into their owning plugin packages, with manifest skills declarations and docs/test path updates.
Validation:
- node --import tsx scripts/sync-plugin-versions.ts --check
- node scripts/run-vitest.mjs src/skills/loading/env-path-guidance.test.ts
- autoreview clean
- Crabbox Azure pnpm check:changed run_59ba76511d57 / lease cbx_cbc6750dad72
- wrapper prepare passed pnpm install --frozen-lockfile, pnpm build, and pnpm check before the oversized full local pnpm test was stopped
Follow-up: #95132 remains as the stacked PR for the rest of the starter-skill/Sherpa/ClawHub work.
* fix(whatsapp): preserve native quote replies
* feat(plugin-sdk): add quote-reply live transport standard
* test(qa-lab): add WhatsApp quote-reply live scenarios
Summary:
- The PR changes the WhatsApp auto-reply first-media failure fallback to resend the saved leading caption chunk and adds a multi-chunk regression test for that failure path.
- PR surface: Source 0, Tests +26. Total +26 across 2 files.
- Reproducibility: yes. Source inspection of current main gives a deterministic path: the first chunk is shift ... fallback shifts `remainingText` again before checking `caption`; this read-only review did not rerun tests.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head b609e44654.
- Required merge gates passed before the squash merge.
Prepared head SHA: b609e44654
Review: https://github.com/openclaw/openclaw/pull/93823#issuecomment-4724923171
Co-authored-by: yetval <yetvald@gmail.com>
* fix(whatsapp): extract GIF metadata and distinguish gifPlayback in media placeholders (fixes#49099)
- Add escapeAttr() helper to sanitize quotes and angle brackets in XML attribute values
- Add extractExternalAdReplyMetadata() to extract title, sourceUrl, body from contextInfo.externalAdReply
- Distinguish GIFs from videos using videoMessage.gifPlayback flag (media:gif vs media:video)
- Enrich image and video placeholders with externalAdReply metadata when available
- Add 5 test cases covering GIF detection, metadata extraction, attribute escaping, and empty fields
* fix(whatsapp): keep GIF metadata in untrusted context
---------
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
* fix(whatsapp): preserve auth on passive terminal stops
* fix(whatsapp): recover stale web auth during relink
* fix(gateway): defer channel stop until qr takeover
The inline-code/fence restore step matched the placeholder index with a
greedy `(\d+)`, so a digit in user text immediately after a code span
(e.g. `code`5) was absorbed into the index, resolved to undefined, and
`?? ""` deleted both the code span and the digit. Terminate the
placeholder index with the existing NUL marker so the index boundary is
unambiguous.
Co-authored-by: Dr Rushindra Sinha <5796457+rushindrasinha@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>