fix(feishu): fall back media replies#98320
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 15, 2026, 10:33 PM ET / July 16, 2026, 02:33 UTC. Summary PR surface: Source +24, Tests +93. Total +117 across 4 files. Reproducibility: yes. at source level. Current main’s media reply path lacks the established unavailable-target fallback, and the focused tests model both returned and thrown Feishu error shapes; the submitted live run additionally proves the repaired allowed-fallback path. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Refresh this canonical branch onto current main, retain the shared fallback helper and explicit thread-safety flag, rerun the focused Feishu tests plus required gates on the exact mergeable head, then land it and close the linked issue and weaker duplicate PR. Do we have a high-confidence way to reproduce the issue? Yes at source level. Current main’s media reply path lacks the established unavailable-target fallback, and the focused tests model both returned and thrown Feishu error shapes; the submitted live run additionally proves the repaired allowed-fallback path. Is this the best way to solve the issue? Yes. Reusing the existing text/card fallback contract and forwarding its explicit safety flag is narrower and less drift-prone than implementing a second media-specific recovery path. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 154d1277e12e. Label changesLabel justifications:
Evidence reviewedPR surface: Source +24, Tests +93. Total +117 across 4 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
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
Review history (5 earlier review cycles)
|
Reverts the r2-vulnerable Layer 4 loopback test that mutated node_modules/@larksuiteoapi/node-sdk at module load. ClawSweeper r2 flagged the node_modules patching as 'merge-risk: 🚨 automation' P1, and dropped rating from 🦪 silver shellfish to 🧂 unranked krab. Removing this test file drops the PR diff from +780/-77 to +392/-77 (50% reduction). Layer 1-3 proof remains: 10 mock-based media tests in media.reply-fallback.test.ts + 3 dispatcher propagation tests in reply-dispatcher.test.ts, all 112/112 passing. The 'real Feishu Open Platform delivery proof' blocker remains in the P1 'real behavior proof' category — same as PR openclaw#98320 (TUARAN) and the other competing Feishu fix. That blocker is maintainer-decision category per the skill §6.7 'Mechanical vs architectural blocker'. PR body is being updated separately to add '## Evidence' top-level heading per checklist openclaw#23 (real-behavior-proof-check.mjs policy).
|
Hi @TUARAN — both of our PRs (#98320 and #98329) are open candidates for #98311 and both are blocked on the same "real Feishu setup proof" requirement. The approaches are essentially the same: route media replies through the existing Rather than having two competing PRs consume maintainer review bandwidth, would you be open to closing #98320 in favor of #98329? Happy to credit you in the PR body or co-author the commit if any of your approach was used. If you prefer to keep #98320 as the canonical branch, I'm also willing to close #98329 and port the dispatcher-forwarding fix + tests over to your branch. Let me know what you think. |
|
I just closed my own attempt (#98329) after comparing the two branches. Both fix the same Feishu image/file withdrawn-reply-target fallback gap by reusing The remaining blocker for both PRs is real Feishu Open Platform proof. If there is anything I can do to help verify the fallback path — e.g., reviewing the mock-based regression tests or running a local branch variation — let me know. |
|
Thanks for comparing the branches and consolidating on #98320. I agree this is the better canonical branch to keep open. The dispatcher forwarding piece is already present here, and the remaining blocker is real Feishu proof rather than patch shape, so I’d rather keep the narrower diff instead of mixing in the larger branch. I’ll keep pushing on the proof path from here. If maintainers later want extra dispatcher-only regression coverage, I can port that minimally instead of merging the broader history. |
5869fdc to
951c75f
Compare
|
Refreshed this PR from current
The PR body now contains the refreshed six-field proof and exact commands. @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
951c75f to
dc9c348
Compare
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: fix(feishu): fall back media replies This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
Merged via squash.
|
* fix(feishu): fall back media replies * test(feishu): polish media fallback coverage * test(feishu): cover media fallback policy wiring --------- Co-authored-by: Peter Steinberger <[email protected]>
Summary
Fixes Feishu image and file delivery when the quoted reply target has been withdrawn or deleted.
sendReplyOrFallbackDirectcontractallowTopLevelReplyFallbackCloses #98311.
Verification
node scripts/run-vitest.mjs extensions/feishu/src/media.test.ts extensions/feishu/src/reply-dispatcher.test.ts(126 tests passed)node_modules/oxfmt/bin/oxfmt --check extensions/feishu/src/media.test.ts extensions/feishu/src/media.ts extensions/feishu/src/reply-dispatcher.ts extensions/feishu/src/send.tsgit diff --check upstream/main...HEAD.agents/skills/autoreview/scripts/autoreview --mode branch --base upstream/main --codex-bin /Applications/ChatGPT.app/Contents/Resources/codex --stream-engine-output(clean; no accepted/actionable findings, correctness 0.9)node_modules/.bin/tsx /private/tmp/feishu-98320-live-proof-20260716.mts(real image and file recovery passed; proof messages cleaned up)upstream/main9c6c8446a7d; exact tested head951c75ff096ddd35d3a0ae99c7de47134fb864d5Real behavior proof
Behavior addressed: Feishu image and file replies no longer disappear when their quoted reply target was withdrawn; the existing guarded fallback delivers them as top-level messages when that fallback is allowed.
Real environment tested: Exact head
951c75ff096ddd35d3a0ae99c7de47134fb864d5on macOS arm64, using the configured real Feishu Open Platform app and a paired Feishu recipient. The run used the current branch's realsendMessageFeishu,sendMediaFeishu, upload, reply-fallback, direct-create, and message-readback paths.Exact steps or command run after this patch:
node_modules/.bin/tsx /private/tmp/feishu-98320-live-proof-20260716.mts. For both image and file cases, the harness created a real Feishu message, withdrew it through the real API, calledsendMediaFeishuwith that withdrawn message asreplyToMessageIdandallowTopLevelReplyFallback: true, read the recovered message back from Feishu, verified its type and receipt, then deleted the proof message.Evidence after fix:
{ "head": "951c75ff096", "environment": "real Feishu Open Platform app + paired recipient", "results": [ { "kind": "image", "withdrawnCode": 230011, "recoveredTopLevel": true, "readbackType": "image", "receiptMatchesReadback": true }, { "kind": "file", "withdrawnCode": 230011, "recoveredTopLevel": true, "readbackType": "file", "receiptMatchesReadback": true } ], "cleanupCompleted": true }Observed result after fix: Both real reply attempts returned Feishu code
230011(The message was withdrawn.). The current OpenClaw path recovered both uploads through top-level creation; Feishu readback reportedimageandfile, both returned message IDs matched the OpenClaw receipts, and all proof messages were removed afterward.What was not tested: Feishu code
231003(message not found) was covered by focused regression tests but not induced in the live tenant. Native topic-thread fallback was not exercised live because it would require creating a user-visible topic scenario; its allow/deny boundary is covered by the focused tests. The live run used one configured Feishu tenant and one paired recipient.