Skip to content

fix(media): pin requester delivery route when task starts#89949

Merged
obviyus merged 14 commits into
openclaw:mainfrom
wangwllu:fix/86034-origin-to-backfill
Jun 22, 2026
Merged

fix(media): pin requester delivery route when task starts#89949
obviyus merged 14 commits into
openclaw:mainfrom
wangwllu:fix/86034-origin-to-backfill

Conversation

@wangwllu

@wangwllu wangwllu commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Detached media generation can start from a requester origin that has a channel but no target. The artifact is generated, but completion delivery fails because the downstream route is incomplete.

Addresses #86034 (missing-target mechanism only; the issue tracks additional delivery mechanisms).

Why This Change Was Made

The requester session already has the complete route when detached work starts. This change snapshots that route into the media task handle by merging the supplied origin with the session delivery context at task creation.

Pinning at task start is important: reading mutable session routing at completion could select a different peer in shared-DM session configurations. The completion path now consumes only the pinned task route; no transport-specific fallback or steady-state session lookup is added.

User Impact

Generated image, video, and music results launched off the direct-reply path can return to the initiating conversation when the supplied origin omitted its target. Later session activity cannot redirect that task's media to another peer.

Evidence

  • Media background family plus subagent announce delivery: 5 files / 138 tests passed.
  • Core test typecheck passed with partial requester-session fixtures.
  • Regressions pin the initiating route, ignore later session drift, and reject same-channel/account-only target fallback across conflicting accounts.

Real behavior proof

Current head targeted proof:

node scripts/run-vitest.mjs run \
  src/agents/tools/media-generate-background-shared.test.ts \
  src/agents/tools/image-generate-background.test.ts \
  src/agents/tools/video-generate-background.test.ts \
  src/agents/tools/music-generate-background.test.ts \
  src/agents/subagent-announce-delivery.test.ts

Result: 5 files, 138 tests passed. The regressions pin lastChannel / lastTo / lastAccountId at task creation, mutate the mocked session route before completion, prove delivery still uses the original peer, reject a target from a conflicting account, strip stale cross-target thread ids, and recover an external session route from an internal requester origin.

Native Telegram Desktop Mantis proof succeeded on attempt 2: https://github.com/openclaw/openclaw/actions/runs/27971069903. Its direct production-runtime probe shows main omitting the generated image completion while candidate 0010944da9ba7fdf8452f8cd24d1cb35c8342187 delivers it back to the requester chat; paired screenshots/GIFs and raw evidence are linked in the Mantis PR comment. Final head 606c94e36b6cb35a20dd6476c78a8307dfe02bd2 is an ancestry-only rebase with the identical changed production blob (162e2d7828d22241e33b3e4f2cd68bb890e81070).

Known scope: this fixes the missing-target mechanism only. Retry asymmetry and other #86034 mechanisms remain separate follow-up work.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 3, 2026
@clawsweeper

clawsweeper Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 21, 2026, 9:12 PM ET / 01:12 UTC.

Summary
The PR moves requester-session loading earlier in sendSubagentAnnounceDirectly, merges deliveryContextFromSession(requesterEntry) into the completion fallback origin, and adds same-channel plus cross-channel regression tests.

PR surface: Source +7, Tests +183. Total +190 across 2 files.

Reproducibility: yes. at source level: current main and v2026.6.9 compute deliverability before requester-session state can backfill to, and the linked issue shows a Telegram requester origin missing to. I did not rerun a live channel repro in this read-only review.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: migration/backfill/repair: src/agents/subagent-announce-delivery.test.ts, serialized state: src/agents/subagent-announce-delivery.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #86034
Summary: This PR is an open candidate fix for the missing-to requester-origin slice of the canonical generated-media completion delivery issue.

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:

  • Get maintainer acceptance, bounding, or rejection of the same-channel requester-session fallback target contract.

Risk before merge

  • [P1] Merging changes the failure mode from no external delivery to delivery through persisted same-channel requester-session route state; stale same-channel lastTo or thread state could target an older chat or thread unless maintainers accept that contract.
  • [P1] The linked canonical issue also includes broader wake-false retry and structured media-handle/output-contract mechanisms, so this PR should close only the missing-to slice unless maintainers split or resolve the remaining work.

Maintainer options:

  1. Accept Same-Channel Session Fallback
    A maintainer can accept requester-session lastTo and thread state as the recovery source when the completion origin lacks a target, relying on the existing cross-channel guard and tests.
  2. Bound Stale Route State
    If persisted same-channel state is too risky, require a freshness or route-binding check before using session state as the generated-media fallback target.
  3. Keep The Contract Open
    If maintainers reject requester-session fallback entirely, pause or close this PR and keep the delivery-target contract decision on the canonical issue.

Next step before merge

  • [P2] The remaining action is maintainer judgment on the fallback delivery-target contract, not a narrow automated code repair.

Security
Cleared: The diff changes TypeScript delivery-context selection and focused tests only; no dependency, workflow, secret, package, or supply-chain surface is changed.

Review details

Best possible solution:

Land this PR only after maintainers explicitly accept same-channel requester-session fallback as the recovery target, or revise it to bound stale same-channel targets before merge.

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

Yes, at source level: current main and v2026.6.9 compute deliverability before requester-session state can backfill to, and the linked issue shows a Telegram requester origin missing to. I did not rerun a live channel repro in this read-only review.

Is this the best way to solve the issue?

Yes for the missing-to slice, but it still needs maintainer acceptance of the fallback contract. The PR fixes the target before the deliverability gate and reuses the existing cross-channel merge guard rather than deriving a transport-specific target from the session key.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 4f7d1f497777.

Label changes

Label justifications:

  • P2: The PR addresses a real generated-media completion delivery failure with bounded channel/session blast radius.
  • merge-risk: 🚨 message-delivery: The diff can turn a silent drop into delivery through persisted same-channel requester-session state, which could misroute generated media if that state is stale.
  • 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): Mantis Telegram Desktop screenshot proof shows the candidate delivering the generated image in a real Telegram chat; MP4 processing was unavailable, but the screenshots were inspectable.
  • proof: sufficient: Contributor real behavior proof is sufficient. Mantis Telegram Desktop screenshot proof shows the candidate delivering the generated image in a real Telegram chat; MP4 processing was unavailable, but the screenshots were inspectable.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. Mantis Telegram Desktop screenshot proof shows the candidate delivering the generated image in a real Telegram chat; MP4 processing was unavailable, but the screenshots were inspectable.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. The PR changes visible Telegram generated-media delivery, so Telegram Desktop proof is relevant and already attached.
Evidence reviewed

PR surface:

Source +7, Tests +183. Total +190 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 14 7 +7
Tests 1 183 0 +183
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 197 7 +190

What I checked:

  • Repository policy applied: Root AGENTS.md and scoped src/agents/AGENTS.md were read fully; the relevant policy treats agent/channel fallback delivery as compatibility-sensitive and requires whole-path review. (AGENTS.md:13, 4f7d1f497777)
  • Current main lacks the backfill before deliverability: Current main normalizes completion/direct/requester origins and computes effectiveDirectOrigin before loading requesterEntry, so the requester session entry cannot fill a missing to before deliveryTarget is resolved. (src/agents/subagent-announce-delivery.ts:1224, 4f7d1f497777)
  • Deliverability requires channel and target: resolveExternalBestEffortDeliveryTarget only marks a target deliverable when both a deliverable channel and normalized to are present, matching the linked missing-to failure mode. (src/infra/outbound/best-effort-delivery.ts:21, 4f7d1f497777)
  • PR head adds the intended fallback: The PR loads requesterEntry before delivery-target resolution, derives deliveryContextFromSession(requesterEntry), and merges it into the completion fallback origin. (src/agents/subagent-announce-delivery.ts:1231, ab0afd549a38)
  • Cross-channel merge guard exists: deliveryContextFromSession projects session last* fields into a delivery context, and mergeDeliveryContext keeps target/account/thread fields from crossing conflicting channels. (src/utils/delivery-context.shared.ts:213, 4f7d1f497777)
  • Latest release also lacks the fix: v2026.6.9 has the same effectiveDirectOrigin / requesterEntry ordering as current main, so this fix is not already shipped. (src/agents/subagent-announce-delivery.ts:1224, c645ec4555c0)

Likely related people:

  • maxpetrusenko: Authored the earlier completion announce delivery-target inheritance work that this PR extends. (role: prior feature author; confidence: high; commits: 8262078ee50c; files: src/agents/subagent-announce-delivery.ts)
  • steipete: Authored requester-agent media completion routing work across the same announce-delivery and media background helper paths. (role: adjacent media-routing contributor; confidence: high; commits: 7f28c8bd07d3; files: src/agents/subagent-announce-delivery.ts, src/agents/tools/media-generate-background-shared.ts)
  • joshavant: Authored the merged direct-message subagent completion delivery fix in the same module and tests. (role: recent adjacent delivery contributor; confidence: medium; commits: b3b962a05152; files: src/agents/subagent-announce-delivery.ts, src/agents/subagent-announce-delivery.test.ts)
  • vincentkoc: Current-main blame and recent commits touch the delivery-target block and empty-completion handoff behavior in this file. (role: recent area contributor; confidence: medium; commits: 108d6d7eca00, e0018382eb00; files: src/agents/subagent-announce-delivery.ts, src/utils/delivery-context.shared.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.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. 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. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jun 3, 2026
@clawsweeper
clawsweeper Bot temporarily deployed to qa-live-shared June 3, 2026 17:45 Inactive
@openclaw-mantis

openclaw-mantis Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Mantis Telegram Desktop Proof

Summary: Mantis captured native Telegram Desktop before/after GIF evidence: main does not show the generated image completion, while this PR delivers it back to the chat.

Main screenshot This PR screenshot
Baseline native Telegram Desktop screenshot Candidate native Telegram Desktop screenshot
Main This PR
Baseline native Telegram Desktop proof GIF Candidate native Telegram Desktop proof GIF

Motion-trimmed clips:

Raw QA files: https://artifacts.openclaw.ai/mantis/telegram-desktop/pr-89949/run-27971069903-2/index.json

@openclaw-barnacle openclaw-barnacle Bot added triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. and removed triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 4, 2026
@wangwllu

wangwllu commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

CI feedback request

check-lint — need help locating the errors

The lint job run 26902096731 reports:

##[error]Unnecessary escape character '/'
##[error]Unnecessary escape character '/'
##[error]Unnecessary escape character '/'
##[error]Unnecessary escape character '/'

Found 0 warnings and 4 errors.
Finished in 14.7s on 9563 files with 242 rules using 8 threads.

The CI log surfaces the rule but no file:line locations. I verified locally:

  • Running the same script (node scripts/run-oxlint-shards.mjs --threads=4) on oxlint 1.67.0 against this branch produces 0 errors, 0 warnings.
  • Running the same script against the PR's merge-base (286e5ffe) also produces 0 errors, 0 warnings.
  • grep -nE '\\/' over the two files this PR touches (src/agents/subagent-announce-delivery.ts, src/agents/subagent-announce-delivery.test.ts) returns no matches.

This suggests one of:

  1. The CI runner is on a different oxlint version where no-useless-escape finds something local 1.67.0 does not (most likely — the action prints with 242 rules; my local shows 242 rules too, but the CI's 9563 files vs my local count may differ).
  2. The 4 errors live in a path my local lint isn't scanning (some shard or workspace I'm not iterating).

Could a maintainer either:

  • re-run the lint with --silent=false / annotation mode disabled so file paths surface, or
  • confirm the oxlint binary version + invocation used in CI so I can reproduce.

I'm happy to fix the escape if it's something this PR introduced; I just can't see where to fix without the location.

Real behavior proof — addressed

Mantis run 26902454818 captured a Telegram Desktop end-to-end with Overall: true (baseline + candidate both pass). I've updated the PR body to reference it under "Real behavior proof", so the policy check should pass on re-run.

@wangwllu

wangwllu commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

PR body updated with live Mantis Telegram Desktop proof (run 26902454818, Overall: true, both baseline + candidate pass). The earlier 'Real behavior proof' policy check ran before Mantis published, so the artifact link was not yet in the body — that should now satisfy the proof gate.

@clawsweeper

clawsweeper Bot commented Jun 4, 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 proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: 🎥 video Contributor real behavior proof includes video or recording evidence. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 4, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label Jun 4, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: 🎥 video Contributor real behavior proof includes video or recording evidence. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. labels Jun 4, 2026
@wangwllu

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@wangwllu

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

2 similar comments
@wangwllu

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@wangwllu

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@steipete

Copy link
Copy Markdown
Contributor

Land-ready verification for 0010944da9ba7fdf8452f8cd24d1cb35c8342187:

Known scope: this lands only the missing-target mechanism. Retry asymmetry and other #86034 mechanisms remain open.

wanglu241 and others added 14 commits June 22, 2026 11:38
…ter session entry

When a media-generation task is created off the direct-reply path (heartbeat,
cron, subagent spawn), `agentTo` is undefined and the persisted
`requesterOrigin` lacks `to`. Every downstream `Boolean(channel && to)` gate
then short-circuits, so the generated artifact is never delivered even though
the artifact exists on disk and `task_runs.status` is later marked failed with
`completion delivery failed after successful generation`.

The requester session entry already carries `lastTo`/`lastChannel`/
`lastAccountId` and is loaded in the same function further down. Merge that
context back into `effectiveDirectOrigin` before the deliverability decision,
as the existing comment at the same site already promises.

Fixes openclaw#86034 (Hypothesis A). Hypothesis B (wake-false skips direct fallback)
remains a separate follow-up - see issue thread for details.
…gram delivery (openclaw#86034)

Locks the mergeDeliveryContext channelsConflict guard so a stale lastChannel that differs from the completion origin's channel cannot import its lastTo. Addresses ClawSweeper's contract question on PR openclaw#89949.

node_modules not available in this worktree; vitest was not run locally. CI is the gate.
oxlint(curly) rejected the bare `if (!params) continue;` continue inside
the regression test added for openclaw#86034. Wrap the body in braces. No logic
change.
@obviyus

obviyus commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Landed via rebase onto main.

  • Scoped tests: node scripts/run-vitest.mjs src/agents/tools/media-generate-background-shared.test.ts src/agents/tools/image-generate-background.test.ts src/agents/tools/video-generate-background.test.ts src/agents/tools/music-generate-background.test.ts src/agents/subagent-announce-delivery.test.ts (5 files / 138 tests passed)
  • Changelog: skipped; release generation owns CHANGELOG.md for normal PRs
  • Land commit: 6a2b993
  • Merge commit: 780f83b

Thanks @wangwllu!

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

Labels

agents Agent runtime and tooling mantis: telegram-visible-proof Mantis should capture Telegram visible proof. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal backlog priority with limited blast radius. 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: M 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.

3 participants