Adds a default-disabled Doctor lint check for WhatsApp responsiveness pressure while keeping real cleanup in the existing doctor --fix path.
Verification:
- Focused WhatsApp responsiveness/contribution Vitest passed (71 tests).
- Changed-file oxfmt passed.
- Changed-file oxlint with core tsconfig passed.
- SDK surface report passed.
- SDK export sync passed.
- git diff --check passed.
- Selected source CLI proof passed earlier on this head: doctor --lint --json --only core/doctor/whatsapp-responsiveness exited 0, ran 1 check, and did not create <state>/identity/device.json.
- Exact-head hosted checks passed/skipped on 39f003931ff8cd93f945e75bf7a480cf2271c910; older cancelled proof/auto-response runs were superseded by passing current runs.
Maintainer notes:
- ClawSweeper platinum hermit / ready for maintainer review.
- Accepted the opt-in lint check id and warning copy on the PR.
- No public config/plugin/SDK/persisted data contract change; default doctor --lint remains unchanged.
Adds a default-disabled Doctor lint check for stale plugin-runtime symlinks while keeping real deletion in the existing legacy doctor --fix cleanup path.
Verification:
- Focused plugin-runtime-symlink/contribution Vitest passed (65 tests).
- Changed-file oxfmt passed.
- Changed-file oxlint with core tsconfig passed.
- SDK surface report passed.
- git diff --check passed.
- Exact-head hosted checks passed/skipped on 287d2230ee.
Maintainer notes:
- ClawSweeper platinum hermit / ready for maintainer look.
- Accepted the new opt-in lint check id and warning copy on the PR.
- Local prepare wrapper pnpm check still fails on the npm shrinkwrap guard, and the same failure reproduces on current origin/main; treated as baseline local gate noise, not PR-caused.
Telegram no longer sends a generic "Something went wrong" fallback after a
final answer was already delivered and a later dispatch/cleanup step failed.
Failures with only partial or no visible output still send the error fallback
and stay retryable.
Related: #87299Closes#90152
Keep CLI session reuse hashes keyed to stable session prompt facts while preserving per-turn room-event message-tool delivery for execution and MCP scoping.
Thread cliSessionBindingFacts from reply assembly through queued/followup CLI runs, make the stable CLI prompt delivery-neutral, and cover production-shaped room-event opts so forced message_tool_only delivery cannot poison binding identity.
Fixes#99372
Release note: Telegram/room-event CLI backends can resume sessions across interactive turns again instead of replaying full history after system-prompt invalidations.
Expose default-disabled Doctor lint findings for legacy plugin dependency state.
The check maps the existing safe cleanup-target detection into structured lint output while keeping real cleanup in the legacy doctor --fix path. Default doctor --lint remains unchanged; explicit --only and --all can include the new warning.
Validation:
- GitHub checks green on head 53c11a6f82
- ClawSweeper: proof sufficient, platinum hermit, ready for maintainer look
- Local post-rebase proof: focused Doctor Vitest, changed-file oxlint, changed-file oxfmt --check, and git diff --check all passed
Maintainer note: WSL maintainer wrapper path is unavailable on this host with Wsl/Service/CreateInstance/0x80072745, so this uses the steerable head-pinned squash path allowed by the current maintainer workflow docs.
Summary:
- The PR changes the docs map generator to escape HTML-significant heading text, regenerates `docs/docs_map.md`, and adds a Vitest regression for HTML-like headings.
- PR surface: Tests +13, Docs 0, Other +10. Total +23 across 3 files.
- Reproducibility: yes. Current main has source headings such as `docs/cli/agents.md:164` with `<id>`, while `docs/docs_map.md:1231` omits it and `scripts/generate-docs-map.mjs:90` strips `<...>` text.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head 261466a2a8.
- Required merge gates passed before the squash merge.
Prepared head SHA: 261466a2a8
Review: https://github.com/openclaw/openclaw/pull/99099#issuecomment-4866739708
Co-authored-by: Mason Huang <masonxhuang@tencent.com>
Approved-by: hxy91819
Summary:
- The PR replaces native i18n conditional-branch regex filtering with an exported linear ASCII scanner and adds focused coverage.
- PR surface: Tests +9, Other +36. Total +45 across 2 files.
- Reproducibility: yes. from source inspection: current main routes conditional-branch native literals through the backtracking-prone regex before inventory output. I did not run a timing benchmark against current main.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head 97464c9635.
- Required merge gates passed before the squash merge.
Prepared head SHA: 97464c9635
Review: https://github.com/openclaw/openclaw/pull/99098#issuecomment-4866733462
Co-authored-by: Mason Huang <masonxhuang@tencent.com>
Approved-by: hxy91819
* fix(imessage): recognize bare hex group chat identifiers as chat targets
A 32-char hex iMessage group chat identifier (as returned by `imsg` for
group chats) with no explicit `chat_identifier:` prefix fell through to
E.164 phone-number normalization. normalizeE164 strips non-digit
characters and prepends `+`, turning
`7d5297154d5f436d83dbbdf03fcc8fdd` into `+75297154543683038` -- a
bogus phone number. Cron/announce delivery then reported
`delivered: true` while silently sending to a nonexistent recipient.
Detect bare 32-char hex strings in both the send-path target parser
(extensions/imessage/src/targets.ts) and the outbound delivery-target
normalizer (extensions/imessage/src/normalize.ts) and route them as
chat_identifier targets, consistent with how an explicit
`chat_identifier:<id>` prefix already resolves.
Fixes#89235.
* refactor(imessage): centralize bare chat identifiers
* refactor(imessage): centralize bare chat identifiers
---------
Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Summary:
- The branch adds `forceMeetEnglishUi()` for Google Meet URLs, applies it to join/create browser opens, canonicalizes browser-created meeting links, and updates focused Google Meet tests.
- PR surface: Source +18, Tests +19. Total +37 across 6 files.
- Reproducibility: yes. Current main opens raw Meet URLs while the browser automation matches English-only lab ... R body provides after-fix CDP output showing non-English pages render expected English labels with `hl=en`.
Automerge notes:
- PR branch already contained follow-up commit before automerge: chore(tooling): add unused agent-cache-store files to knip optional a…
- PR branch already contained follow-up commit before automerge: fix(google-meet): repair non-Latin mic regex matching boundary
- PR branch already contained follow-up commit before automerge: revert(tooling): preserve current main deadcode allowlist guard
- PR branch already contained follow-up commit before automerge: revert(tooling): perfectly match origin/main deadcode list
- PR branch already contained follow-up commit before automerge: revert: match origin/main deadcode list exactly
Validation:
- ClawSweeper review passed for head 880a41b6f0.
- Required merge gates passed before the squash merge.
Prepared head SHA: 880a41b6f0
Review: https://github.com/openclaw/openclaw/pull/89671#issuecomment-4608725456
Co-authored-by: Chen Chia Yang <unayung@gmail.com>
Approved-by: hxy91819
* feat(signal): add target aliases
* fix(signal): canonicalize alias delivery targets
* fix(signal): harden alias target resolution
* test(signal): cover formatted media aliases
* test(signal): align approval alias proof with request shape
* Reuse Signal alias map for directory listing
* fix(subagents): match requesterSessionKey when controllerSessionKey differs in list filter
The listControlledSubagentRuns filter used a fallback (||) to pick one
key for matching. When controllerSessionKey was set but did not match the
caller's session key, the filter returned false even though
requesterSessionKey could have matched.
Change the filter to OR logic: if either controllerSessionKey or
requesterSessionKey matches the caller key, include the run.
Fixes#75593
* fix(subagents): add braces for lint compliance and real behavior proof
- Add braces around if-return statements to pass eslint(curly)
- Add evidence script verifying OR-match filter behavior
Evidence (3 scenarios, all pass):
S1: controllerKey=agent:main:main, requesterKey=telegram → 1 result (PASS)
S2: controllerKey=telegram, requesterKey=agent:main:main → 1 result (PASS)
S3: both keys unrelated → 0 results (PASS — scope isolation)
🦞 diamond lobster: L2 evidence (isolated tsx + real exports)
Ref. https://github.com/openclaw/openclaw/pull/99410
* fix(subagents): replace evidence scripts with focused regression tests
- Remove evidence/ scripts (failing check-guards per review)
- Add listControlledSubagentRuns test coverage in subagent-control.test.ts
- Three scenarios: controller match, requester match (new fix), scope isolation
Ref. https://github.com/openclaw/openclaw/pull/99410
* refactor(subagents): clarify read visibility ownership
---------
Co-authored-by: sheyanmin <sheyanmin@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>