Skip to content

fix(outbound): reject reserved Telegram targets before directory/default fallback#94107

Merged
obviyus merged 14 commits into
openclaw:mainfrom
zhangguiping-xydt:feat/issue-91372
Jun 25, 2026
Merged

fix(outbound): reject reserved Telegram targets before directory/default fallback#94107
obviyus merged 14 commits into
openclaw:mainfrom
zhangguiping-xydt:feat/issue-91372

Conversation

@zhangguiping-xydt

@zhangguiping-xydt zhangguiping-xydt commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

What problem does this PR solve?

  • Fixes Telegram outbound target resolution for provider-reserved words such as current, self, this, and me.
  • A reserved word that is also a real configured Telegram group/channel target now resolves through the directory first, instead of being rejected before lookup.
  • A reserved word with no directory match still fails closed before plugin/default fallback.
  • Target validation and route-miss paths now keep only validated directory targets, so downstream delivery code cannot accidentally keep using the original unsafe input next to targetResolutionError or after route canonicalization misses.
  • Isolated cron delivery now uses the same directory-first reserved-literal behavior before returning a reserved-target error.

Why does this matter now?

  • The previous PR shape protected session-reference words, but it could break existing Telegram routes if a real configured group/channel was named or handled as one of those words.
  • It also left delivery-path footguns: callers that did not check targetResolutionError first could still see the original unresolved target in resolvedTo, and isolated cron delivery could return the reserved-target error before the directory-aware resolver ran.
  • The practical user impact is message-delivery correctness: real Telegram directory entries should remain routable, while missing reserved literals should not be treated as literal Telegram destinations.

What is the intended outcome?

  • current resolves to a configured Telegram directory entry when that entry exists.
  • telegram:current follows the same directory-first behavior as bare current.
  • current fails closed with a reserved-target error when there is no matching Telegram directory entry.
  • Gateway delivery planning uses the same directory-aware target result, failed target validation removes resolvedTo, and isolated cron delivery gives configured directory entries the same reserved-literal preservation before failing closed on misses.

What is intentionally out of scope?

  • No Telegram schema, migration, permission, auth, or live-send behavior changes.
  • No new public target syntax beyond using the already introduced plugin reserved-literal contract.
  • No attempt to make bare reserved words literal Telegram usernames after a directory miss; users must use explicit handle/id syntax for literal destinations.
  • No live Telegram network send in this proof environment.

What does success look like?

  • Directory-backed Telegram targets named/handled as current keep working.
  • Reserved words that are not directory entries remain blocked before fallback normalization.
  • Delivery-plan error paths do not expose unsafe original inputs as resolved destinations.
  • Focused regression tests and production-path resolver/gateway proof both pass on the current head.

What should reviewers focus on?

  • The routing order in resolveMessagingTarget: directory matches are preserved before reserved-literal rejection, and reserved literals cannot continue to plugin/default fallback after a miss.
  • The session-route preparation path in resolveAgentDeliveryPlanWithSessionRoute: it now uses the directory-aware resolver and clears resolvedTo on target-resolution errors.
  • The compatibility boundary for Telegram users with literal reserved-word usernames: explicit handle/id syntax remains the intended path when there is no directory match.

Fix classification: root-cause compatibility and safety fix for Telegram outbound target resolution.

Root cause: reserved-literal rejection and session-route planning were split across sync outbound validation, the directory-aware resolver, gateway delivery planning, and isolated cron delivery. Core could not consistently distinguish a real Telegram directory entry named current from an unsafe session-reference literal, and route/error paths could keep raw reserved input after validation failed or route canonicalization missed.

Why this is the root cause: the resolver must first identify whether the input is a configured destination, then apply provider-reserved literal safety before plugin/default resolution; delivery planning and cron delivery must only expose destinations that have passed the directory-aware target owner.

Related PR scan: this is a repair/update to the existing PR #94107 for #91372. I did not open a competing PR; the remaining public-contract questions are disclosed below for maintainer review.

  • Fix classification: Root-cause compatibility and safety fix for Telegram outbound target resolution.
  • Root cause: Reserved-literal safety and delivery planning were split around the directory-aware resolver, so a configured Telegram destination named current could be rejected before lookup while directory misses or route misses could still leak raw reserved input across gateway or cron delivery paths.
  • Why this is root-cause fix: resolveMessagingTarget is kept as the source of truth for configured destinations and reserved-literal misses. Directory lookup owns real destinations, reserved-literal rejection owns misses before plugin/default resolution, and gateway/cron delivery only keep validated targets after successful directory-aware resolution.
  • Maintainer-ready confidence: High after sync-main, focused resolver/outbound validation, cron delivery validation, raw-channel-fetch boundary lint, and ClawSweeper commit review all passed on the current repair branch.
  • What did NOT change: This PR does not change schema, migration, permission, auth, token, live-send, provider setup, public target syntax, or non-Telegram routing behavior.
  • Architecture / source-of-truth check: Core target resolution remains the source-of-truth in resolveMessagingTarget; Telegram only declares its reserved literals/capabilities, and gateway/session-route delivery consumes the resolver result instead of duplicating destination ownership.
  • Patch quality notes: Patch-quality warnings are test/body-risk guardrails, not runtime fallbacks: the expect.any(Function) shape assertion is confined to test fixtures, explicit return undefined keeps non-matching normalization branches clear, and fallback wording describes the old path being blocked rather than a new fallback being added.
  • Related open PR scan: This updates my existing open PR fix(outbound): reject reserved Telegram targets before directory/default fallback #94107 for Gateway session resolver should reject literal target="current" strings #91372 rather than opening a competing PR; the optional plugin reservedLiterals contract remains explicitly disclosed for maintainer review.
  • Risk labels considered: message-delivery, session-state, and public plugin SDK contract.
  • Risk explanation: The risky boundary is Telegram target routing order for provider-reserved words that may also be real configured directory destinations.
  • Why acceptable: The change allows reserved words only after a concrete directory match; missing directory entries still fail closed before fallback/session-route handling, and focused resolver, outbound, Telegram target, and boundary lint checks pass.

Linked context

Closes #91372

Related #94107

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: Telegram reserved targets like current should route to a real configured Telegram group/channel named or handled as current, but still fail closed when no directory entry exists.
  • Real environment tested: production OpenClaw modules with the real Telegram plugin, config-backed Telegram groups, the production target resolver, and the gateway delivery-plan/session-route path.
  • Exact steps or command run after this patch:
pnpm exec tsx <production-path proof script>
  • Evidence after fix:
{
  "proof": "telegram-current-directory-vs-reserved-miss",
  "registry": {
    "pluginId": "telegram",
    "channelId": "telegram",
    "source": "proof",
    "hasDirectory": true,
    "hasSessionRoute": true,
    "reservedLiterals": ["current", "self", "this", "me"]
  },
  "directoryHit": {
    "ok": true,
    "target": {
      "to": "telegram:@current",
      "kind": "group",
      "display": "current",
      "source": "directory",
      "resolutionSource": "directory"
    }
  },
  "prefixedHit": {
    "ok": true,
    "target": {
      "to": "telegram:@current",
      "kind": "group",
      "display": "current",
      "source": "directory",
      "resolutionSource": "directory"
    }
  },
  "reservedMiss": {
    "ok": false,
    "error": "Reserved target \"current\" for Telegram cannot be used as a literal destination. Provide an explicit id or handle. Hint: <chatId>"
  },
  "gatewayPlan": {
    "resolvedChannel": "telegram",
    "resolvedTo": "telegram:@current",
    "deliveryTargetMode": "explicit",
    "targetResolutionError": null
  },
  "heartbeatReservedMiss": {
    "channel": "none",
    "reason": "no-target"
  },
  "checks": {
    "directoryHitOk": true,
    "prefixedHitOk": true,
    "directoryMissFailClosed": true,
    "gatewayResolvedFromDirectory": true,
    "heartbeatReservedMissFailClosed": true
  }
}
  • Observed result after fix: bare current and prefixed telegram:current both resolve through the Telegram directory when a config-backed directory entry exists; the same resolved target flows into gateway delivery planning as telegram:@current; a missing directory entry returns the reserved-target error instead of normalizing to an unintended literal destination; heartbeat delivery with missing current returns channel: "none" / reason: "no-target" before Telegram session-route canonicalization.
  • What was not tested: no outbound Telegram message was sent to the public Telegram network.
  • Proof limitations or environment constraints: this proof exercises the production Telegram plugin and OpenClaw resolver/delivery-plan path with config-backed directory data; it does not require or use a Telegram bot token.
  • Before evidence: the production-path proof showed current being normalized as telegram:@current before directory/miss handling; after the resolver change, reserved literals stay on the directory-first path and fail closed only after a directory miss.

Tests and validation

Which commands did you run?

pnpm exec vitest run --config test/vitest/vitest.infra.config.ts src/infra/outbound/target-resolver.test.ts
pnpm exec vitest run --config test/vitest/vitest.infra.config.ts src/infra/outbound/target-resolver.test.ts src/infra/outbound/agent-delivery.test.ts src/infra/outbound/targets.test.ts src/infra/outbound/targets.shared-test.ts extensions/telegram/src/targets.test.ts
pnpm exec vitest run --config test/vitest/vitest.cron.config.ts src/cron/isolated-agent/delivery-target.test.ts
pnpm run lint:tmp:no-raw-channel-fetch

Result:

Validation target-resolver-reserved-exact-only: pass
Test Files  1 passed (1)
Tests       13 passed (13)

Validation focused-outbound-cron-reserved-exact-only: pass
Test Files  4 passed (4)
Tests       113 passed (113)

Validation cron-delivery-reserved-exact-only: pass
Test Files  1 passed (1)
Tests       54 passed (54)

Validation no-raw-channel-fetch-reserved-exact-only: pass
$ node scripts/check-no-raw-channel-fetch.mjs

What regression coverage was added or updated?

  • target-resolver.test.ts now covers directory-first resolution for both current and telegram:current, fail-closed behavior after a directory miss, and exact-only reserved-literal directory preservation so me does not match a substring-only directory entry such as memes.
  • agent-delivery.test.ts now covers clearing resolvedTo when route preparation/target validation fails, preserving the stored target error, and preserving the directory-resolved target when session-route canonicalization itself cannot produce a route.
  • delivery-target.test.ts now covers isolated cron delivery resolving a reserved explicit Telegram target through a configured directory entry before returning any reserved-target error.
  • targets.test.ts now covers heartbeat delivery preserving directory hits for reserved literals and failing closed when a heartbeat reserved literal misses the directory.
  • The shared direct outbound target tests stayed green, confirming direct fallback still rejects bare Telegram reserved literals instead of treating them as normal literal targets.

What failed before this fix, if known?

  • current returned a reserved-target error before the resolver checked configured Telegram directory entries.
  • A session-route target validation error could leave the original unsafe resolvedTo value visible next to targetResolutionError.
  • Isolated cron delivery could return the sync reserved-target error before the directory-capable resolver preserved a configured Telegram directory entry named current.
  • Reserved-literal directory preservation used the normal fuzzy directory match, so a reserved word like me could match a substring-only entry such as memes before the fail-closed reserved check ran.

If no test was added, why not?

  • Tests were added/updated for the directory-first behavior, directory-miss fail-closed behavior, and delivery-plan error path.

Test guardrail rationale:

  • The resolver tests protect both sides of the compatibility boundary: existing real Telegram directory entries keep routing, while missing reserved literals still stop before fallback.
  • The delivery tests protect the safety boundary: failed target validation and route misses cannot leave a destination-shaped raw reserved literal for downstream code to reuse.
  • The cron delivery test protects the scheduled/isolated delivery surface so it follows the same directory-first behavior as gateway delivery.
  • The shared target tests protect direct outbound behavior so this repair does not accidentally re-enable reserved words as literal plugin/default destinations.

Risk checklist

Did user-visible behavior change? (Yes/No)

Yes. A real Telegram directory entry named/handled as current, self, this, or me can now be reached instead of being rejected before lookup; missing entries still fail closed.

Did config, environment, or migration behavior change? (Yes/No)

No.

Did security, auth, secrets, network, or tool execution behavior change? (Yes/No)

No new network/auth/tool execution behavior. The safety posture is preserved for directory misses and strengthened on validation errors by clearing resolvedTo.

What is the highest-risk area?

Telegram target routing order for provider-reserved literals, especially compatibility between real directory entries and fail-closed reserved words.

How is that risk mitigated?

The resolver and delivery paths only allow reserved literals after an exact concrete directory match on id/name/handle after prefix stripping. If the directory does not contain an exact matching Telegram group/channel, the reserved literal still fails closed before plugin/default resolution. Gateway and cron delivery paths no longer expose the original unsafe target after validation failure or route canonicalization miss.

Scope boundary and patch quality notes:

  • The word "fallback" in this PR refers to the existing plugin/default target-resolution stages, not to a silent mitigation path.
  • The larger diff size comes from the existing PR's SDK contract/tests plus this repair's resolver/delivery regression coverage; this update stays within the existing PR scope and does not add a second feature.
  • The public contract risk is the existing optional plugin reserved-literal field. This update narrows the behavior by preserving directory compatibility before applying that reserved-literal guard.

Current review state

What is the next action?

Ready for maintainer review after the PR branch/body update and fresh checks.

What is still waiting on author, maintainer, CI, or external proof?

No known author-side code or test follow-up remains. The only proof limitation is that the production-path Telegram proof does not send a live Telegram network message. Maintainers still need to accept the existing SDK contract and compatibility choice for reserved Telegram literals.

Which bot or reviewer comments were addressed?

  • RF-001 triage: mock-only-proof: addressed with production-path proof using the real Telegram plugin, production resolver, and gateway delivery-plan path; live Telegram network send remains disclosed as not tested.
  • RF-002 real gateway/message-action or Telegram proof for target: "current": addressed with current-head production-path proof showing directory hit for current and a fail-closed reserved error on directory miss.
  • RF-003 real behavior proof request: addressed by replacing mock-only proof with production module proof and copied runtime output in this PR body.
  • RF-004 new optional SDK field requires maintainer acceptance: disclosed as a maintainer contract decision; this repair does not expand that API further.
  • RF-005 compatibility risk for bare Telegram reserved targets: addressed by preserving real directory matches before fail-closed rejection, and disclosed that literal non-directory destinations still need explicit handle/id syntax.
  • RF-006 proof still helper/mock based: addressed with production Telegram plugin + resolver + gateway delivery-plan proof after the patch.
  • RF-007 maintainer review needed for SDK field and compatibility choice: disclosed; author-side code/test/proof updates are complete, maintainer contract review remains.
  • RF-008 explicit reserved targets reaching Telegram session routing: addressed by resolving reserved explicit targets through directory-capable target resolution before session-route planning, preserving a target-resolution error after directory miss instead of handing raw current to Telegram route parsing.
  • RF-009 heartbeat reserved-target misses: addressed by making heartbeat session-route refinement stop delivery when directory-capable target resolution returns the reserved-target error after a directory miss.
  • RF-010 src/infra/outbound/targets.test.ts: addressed with focused heartbeat coverage for both directory-hit routing and directory-miss fail-closed behavior.
  • RF-011 resolver/agent-delivery/Telegram target tests: addressed by the current-head focused outbound and Telegram suite covering resolver, gateway delivery, direct outbound target fallback, and Telegram target behavior.
  • RF-012 after-fix heartbeat proof: addressed with production-path Telegram proof showing heartbeatReservedMiss returns channel: "none" and reason: "no-target" for missing current.
  • RF-013 latest proof/status signal: addressed by updating this PR body with current-head validation and the latest delivery-path, cron, and exact-match review fixes; proof remains proof: sufficient, while live Telegram Desktop proof is disclosed as optional maintainer-requested transport evidence.
  • Latest delivery-path review finding: addressed by preserving a directory-resolved reserved target when session-route canonicalization misses, instead of returning raw current.
  • Latest isolated cron review finding: addressed by letting cron delivery run directory-capable target resolution for reserved literals before returning a reserved-target error.
  • Latest exact-match review finding: addressed by requiring reserved-literal directory preservation to match exact id/name/handle after prefix stripping, with regression coverage for me not matching memes.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: telegram Channel integration: telegram gateway Gateway runtime size: M triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 17, 2026
@clawsweeper

clawsweeper Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 25, 2026, 11:33 AM ET / 15:33 UTC.

Summary
Adds a reservedLiterals channel target resolver contract and Telegram-specific reserved words so outbound, gateway, heartbeat, and cron target resolution preserves exact directory hits for current-style names while failing closed on directory misses.

PR surface: Source +268, Tests +576, Docs +4. Total +848 across 19 files.

Reproducibility: yes. Source inspection shows current main and v2026.6.10 still normalize Telegram current as target-shaped and have no reserved-literal miss guard; the linked issue also documents production incidents, though I did not run a live pre-fix send.

Review metrics: 2 noteworthy metrics.

  • Plugin API surface: 1 optional field added. reservedLiterals changes the channel plugin contract, so maintainer acceptance matters beyond normal CI.
  • Reserved literal policy: 4 Telegram literals guarded after directory miss. The exact words define the compatibility boundary between preserved configured directory targets and newly fail-closed bare literals.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #91372
Summary: This PR is the active open fix candidate for the canonical reserved Telegram target issue; same-root duplicate reports and earlier unmerged PR attempts are closed.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Have a maintainer explicitly accept the reservedLiterals plugin API and Telegram fail-closed compatibility/security policy before merge.

Risk before merge

  • [P1] The PR adds a new optional plugin API field, so maintainers need to accept messaging.targetResolver.reservedLiterals as the long-term channel contract.
  • [P1] Existing Telegram users who intentionally used bare current, self, this, or me as non-directory literal destinations will now fail closed and need explicit handle/id syntax.
  • [P2] The routing order is security-sensitive: exact directory hits are preserved, but misses are intentionally blocked before plugin/default fallback to avoid wrong-target delivery.

Maintainer options:

  1. Accept the contract and land after green checks (recommended)
    Maintainers can explicitly accept the new reserved-literals plugin API and the Telegram fail-closed policy, then merge once required checks are green.
  2. Narrow the contract before merge
    If maintainers do not want this as a plugin SDK seam, replace the generic field with a narrower maintainer-approved Telegram/core boundary before merge.
  3. Pause until routing policy is decided
    If the compatibility/security choice is not ready, keep the PR open or close it in favor of a new maintainer-owned design rather than landing a public API accidentally.

Next step before merge

  • [P2] The remaining blocker is maintainer acceptance of the plugin API and Telegram compatibility/security policy, not a narrow automated code repair.

Security
Needs attention: No supply-chain, dependency, secret, or auth handling regression was found, but the PR intentionally changes a security-sensitive wrong-target boundary.

Review details

Best possible solution:

Land this PR or a maintainer-approved equivalent after explicitly accepting the reservedLiterals plugin contract and Telegram fail-closed compatibility/security policy.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection shows current main and v2026.6.10 still normalize Telegram current as target-shaped and have no reserved-literal miss guard; the linked issue also documents production incidents, though I did not run a live pre-fix send.

Is this the best way to solve the issue?

Yes for the code shape, with a maintainer gate. A plugin-owned literal list plus core directory-first/fail-closed resolution is cleaner than hardcoding Telegram names in scattered callers, but the new API and compatibility policy still need explicit maintainer acceptance.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 82a6a57330cd.

Label changes

Label justifications:

  • P1: The PR addresses a broken Telegram delivery/security workflow where reserved session words can route messages toward the wrong target.
  • merge-risk: 🚨 compatibility: Bare Telegram destinations named current, self, this, or me without directory entries will now fail closed unless users switch to explicit handle/id syntax.
  • merge-risk: 🚨 message-delivery: The diff changes outbound, gateway, heartbeat, and cron target selection, so an incorrect routing order could drop or misroute Telegram messages.
  • merge-risk: 🚨 security-boundary: The fix intentionally blocks reserved literals before fallback to prevent wrong-target delivery across a Telegram/session boundary.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (screenshot): The PR body and later comment include after-fix production-path output plus a live Telegram Desktop screenshot/log showing directory-hit routing, directory-miss failure, and a redacted Telegram API send success.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and later comment include after-fix production-path output plus a live Telegram Desktop screenshot/log showing directory-hit routing, directory-miss failure, and a redacted Telegram API send success.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The PR body and later comment include after-fix production-path output plus a live Telegram Desktop screenshot/log showing directory-hit routing, directory-miss failure, and a redacted Telegram API send success.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. The PR changes visible Telegram delivery behavior for reserved target words, so Telegram-visible proof is appropriate and has been supplied.
Evidence reviewed

PR surface:

Source +268, Tests +576, Docs +4. Total +848 across 19 files.

View PR surface stats
Area Files Added Removed Net
Source 12 306 38 +268
Tests 5 580 4 +576
Docs 2 5 1 +4
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 19 891 43 +848

Security concerns:

  • [medium] Accept the fail-closed Telegram routing boundary — src/infra/outbound/target-resolver.ts:515
    The new reserved-literal miss guard prevents fallback to unintended Telegram destinations, but it also changes which bare targets are accepted; maintainers need to approve this compatibility/security policy before merge.
    Confidence: 0.84

What I checked:

  • Repository policy read: Read the full root policy plus scoped outbound, channel, gateway, extensions, docs, and Telegram maintainer notes; plugin API, compatibility, message delivery, security-boundary, and real Telegram proof guidance applies. (AGENTS.md:1, 82a6a57330cd)
  • Current main lacks the guard: Current main resolves id-like targets, then directory, then plugin/normalized fallback without checking reserved Telegram literals after a directory miss. (src/infra/outbound/target-resolver.ts:401, 82a6a57330cd)
  • Latest release lacks the guard: The latest release tag v2026.6.10 has the same resolver flow without the reserved-literal miss guard, so the fix is not already shipped. (src/infra/outbound/target-resolver.ts:401, aa69b12d0086)
  • PR fail-closed source path: The PR detects reserved literals before id-like resolution, keeps exact directory hits eligible, and returns a reserved-target error before plugin/default fallback after a directory miss. (src/infra/outbound/target-resolver.ts:429, 48ea957cab89)
  • New plugin API surface: The PR adds optional messaging.targetResolver.reservedLiterals to the channel messaging adapter type, making this a plugin contract decision rather than only a Telegram-local fix. (src/channels/plugins/types.core.ts:611, 48ea957cab89)
  • Telegram declares reserved literals: Telegram declares current, self, this, and me through the new resolver field while keeping existing target prefix and normalization ownership in the plugin. (extensions/telegram/src/channel.ts:833, 48ea957cab89)

Likely related people:

  • steipete: GitHub history shows repeated recent work on outbound target resolution, agent delivery, and shared target helpers, including the channel target resolution API refactor and docs for outbound helpers. (role: area history contributor; confidence: medium; commits: c4f0da00a9fe, b4a63886af4b, ffc6bc0be0b2; files: src/infra/outbound/target-resolver.ts, src/infra/outbound/agent-delivery.ts, src/infra/outbound/targets-resolve-shared.ts)
  • vincentkoc: Recent commits touch Telegram channel code, plugin type surfaces, and outbound/channel routing areas adjacent to this PR's plugin contract and Telegram routing behavior. (role: recent adjacent owner; confidence: medium; commits: e012f2cd3cc8, 6cb631afc9c5, 6eb04c8aabdb; files: extensions/telegram/src/channel.ts, src/channels/plugins/types.core.ts, src/infra/outbound/target-resolver.ts)
  • scotthuang: The latest GitHub history for target-resolver.ts includes direct-only target routing changes that the PR body says it had to preserve while adding reserved-literal behavior. (role: recent target resolver contributor; confidence: medium; commits: 0c76a98f103f; files: src/infra/outbound/target-resolver.ts)
  • obviyus: Repository history shows recent Telegram channel work, and the current PR head contains an obviyus commit distilling the reserved-target delivery cleanup. (role: recent Telegram contributor and branch maintainer contributor; confidence: medium; commits: da92615816b6, f1e303404c98, 48ea957cab89; files: extensions/telegram/src/channel.ts, src/infra/outbound/agent-delivery.ts, src/infra/outbound/target-resolver.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jun 17, 2026
@zhangguiping-xydt
zhangguiping-xydt marked this pull request as draft June 18, 2026 03:18
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 18, 2026
@zhangguiping-xydt
zhangguiping-xydt marked this pull request as ready for review June 18, 2026 05:30
@openclaw-barnacle openclaw-barnacle Bot added triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. proof: supplied External PR includes structured after-fix real behavior proof. and removed proof: supplied External PR includes structured after-fix real behavior proof. triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 18, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. proof: sufficient ClawSweeper judged the real behavior proof convincing. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 18, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 18, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 18, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 20, 2026
@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

@obviyus when you have a chance, could you please take a maintainer look at this Telegram target-resolution fix?

The PR preserves configured Telegram targets named like reserved literals (current, self, this, me) while keeping missing reserved literals fail-closed. The PR body has the behavior summary and evidence, and the branch has been synced with current main.

@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

Live Telegram proof

PR 94107 live Telegram proof

Live proof run against PR head c6bd94f535e6 on 2026-06-24:

  • Telegram Desktop sent a real message to the configured bot to establish a live private Telegram chat.
  • PR branch code resolved the reserved literal current through a directory entry to that live Telegram chat.
  • The same run verified a directory miss for current fails closed with Reserved target "current" for Telegram cannot be used as a literal destination....
  • The resolved directory target was then sent through sendMessageTelegram, producing Telegram API success:
[telegram] outbound send ok accountId=default chatId=<redacted> messageId=58 operation=sendMessage deliveryKind=text chunkCount=1
live Telegram proof sent
nonce: oc-pr94107-live-20260624T143235Z-7521
resolved target: telegram:<redacted>
sent message id: 58
missing current error: Reserved target "current" for Telegram cannot be used as a literal destination. Provide an explicit id or handle. Hint: <chatId>

Local artifact paths:

  • Redacted public image: /Users/zhangguiping/daily_pr_work/proofs/openclaw-pr-94107-evidence/pr-94107-live-telegram-proof-public.png
  • Full local screenshot with private chat id: /Users/zhangguiping/daily_pr_work/proofs/openclaw-pr-94107-evidence/pr-94107-live-telegram-proof.png
  • Proof result JSON: /Users/zhangguiping/daily_pr_work/proofs/openclaw-pr-94107-evidence/live-telegram-proof-result.json

张贵萍 and others added 14 commits June 25, 2026 08:35
The sync reserved-literal check in resolveOutboundTargetWithPlugin was
suppressing heartbeat routes to directory entries whose names match
reserved literals (e.g., a Telegram group named "current"). Skip the
check for heartbeat mode so the async resolveChannelTarget →
resolveMessagingTarget path can do directory-first lookup before
deciding.
…literal rejection in resolveMessagingTarget

Move the reserved-literal check from before directory lookup to after directory
miss, so configured Telegram groups/channels whose directory key is a reserved
word (current, self, this, me) still resolve through the directory before
failing closed. The reserved check now runs only after the directory returns no
match and before plugin fallback resolution.

Update the regression test to verify directory-first ordering: a configured
directory entry named current resolves successfully, and a directory miss with
a reserved literal fails with the descriptive error.
…esolver

In resolveAgentDeliveryPlanWithSessionRoute, reserved-literal errors from the
sync outbound target check are no longer treated as fatal. Instead, the path
proceeds to resolveOutboundSessionRoute which calls resolveMessagingTarget,
already fixed to do directory-first lookup before rejecting reserved literals.

This preserves configured Telegram directory entries named like reserved words
(current, self, this, me) through the explicit agent/gateway delivery path.

Update docs to reflect directory-first ordering.
Keep reserved-target detection behavior unchanged while routing callers through a shared helper so future changes stay localized.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@obviyus

obviyus commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Landed via rebase onto main.

  • Scoped tests: pnpm tsgo:core; pnpm exec oxfmt --check --threads=1 src/infra/outbound/agent-delivery.ts src/infra/outbound/target-resolver.ts src/infra/outbound/targets-resolve-shared.ts; node scripts/run-vitest.mjs src/infra/outbound/agent-delivery.test.ts src/infra/outbound/target-resolver.test.ts src/infra/outbound/targets.test.ts src/infra/outbound/target-errors.test.ts
  • Live proof: targeted Telegram reserved-target proof passed; directory hit sent and was observed, directory miss failed closed.
  • Changelog: not updated; release generation owns CHANGELOG.md for normal PRs.
  • Land commit: 9c6a597
  • Merge commit: 8bc069f

Thanks @zhangguiping-xydt!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram docs Improvements or additions to documentation gateway Gateway runtime mantis: telegram-visible-proof Mantis should capture Telegram visible proof. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P1 High-priority user-facing bug, regression, or broken workflow. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: L status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gateway session resolver should reject literal target="current" strings

2 participants