Skip to content

fix(feishu): preserve button command values in fallback text and add Feishu comment guidance with callback privacy#94385

Merged
steipete merged 13 commits into
openclaw:mainfrom
xialonglee:fix/issue-69754-feishu-approval-fallback
Jul 2, 2026
Merged

fix(feishu): preserve button command values in fallback text and add Feishu comment guidance with callback privacy#94385
steipete merged 13 commits into
openclaw:mainfrom
xialonglee:fix/issue-69754-feishu-approval-fallback

Conversation

@xialonglee

@xialonglee xialonglee commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

When Feishu chat or document comments strip interactive blocks (buttons, cards), the fallback text rendered by renderMessagePresentationFallbackText only preserved URL-type button targets. Command buttons (with .value or .action.command / .action.type === "callback") were silently dropped — users saw a bare button label like - Approve with no way to act on it. On Feishu comment threads, no guidance was offered to explain that interactive buttons are unsupported and cannot be used.

The fix also originally exposed legacy opaque value fields as visible text, which crossed the callback privacy boundary. A follow-up review fix tightened this to only render explicit typed action.type === "command" values.

  • Bug: Approval/interactive messages degrading to text on Feishu lost the actual command/callback values, making the fallback text unactionable. Users had no way to know what command to type manually.
  • What this PR changes:
    • src/interactive/payload.ts: renderMessagePresentationFallbackText now calls resolveMessagePresentationControlValue for each button to extract its command value when no URL is present and action.type === "command". These values are rendered as inline code (e.g., - Deny: \/approve req_1 deny`) so the user can copy and type them manually. Legacy opaque valuefields andaction.type === "callback"` values remain private — only the button label is shown.
    • extensions/feishu/src/outbound.ts: When interactive content with command-type actions is detected in a Feishu comment thread, appends a user-friendly guidance line: > Interactive buttons are unavailable in Feishu document comments. You can type the command shown above manually. The guidance is gated on a local hasRenderedCommandAction helper (not exposed through public SDK) that checks for actual action.type === "command" buttons — excluding buttons where URL/webApp overrides the command text in fallback rendering, and disabled buttons.
    • Test updates across payload.test.ts and outbound.test.ts to assert the new fallback format.
    • Added JSDoc to renderMessagePresentationFallbackText documenting the typed command fallback semantics for SDK consumers.
    • Updated docs/plugins/message-presentation.md with a "Button value fallback visibility" section documenting the command/callback/legacy value privacy contract for plugin authors.
  • Fixes Approval UX on Feishu needs clearer fallback guidance when interactive buttons are unavailable or approval degrades to text #69754

Review Fixes

  • P1 — type-narrow channelData.feishu marker read (e8da4b3b39): ctx.payload.channelData?.feishu?.hasRenderedCommandAction failed check-prod-types, check-test-types, check-additional-extension-package-boundary, and QA Smoke CI with TS2339 because channelData is typed as {}. Fixed by narrowing with isRecord() before reading the marker — matching the same pattern used in renderFeishuPresentationPayload at line 337. 1 file +6/-1.
  • P1 — callback privacy: action.type === "callback" values are no longer rendered in fallback text. These are opaque channel/plugin data, not manual commands. Additionally, legacy .value fields (without a typed action) are also kept private — only explicit action.type === "command" values are rendered as copyable text. This addresses the merge-risk: 🚨 security-boundary concern flagged by ClawSweeper.
  • P2 — gate Feishu guidance on command action: Feishu comment thread guidance now checks for actual action.type === "command" buttons, instead of the broader isMessagePresentationInteractiveBlock which matched any buttons/selects blocks. This ensures the "You can type the command shown above manually" text only appears when a copyable command is actually rendered in the fallback text — avoiding misleading guidance on label-only fallbacks (callback, legacy value, or URL-only buttons).
  • P2 — omit guidance when URL overrides command text: When a command button also has url/webApp/web_app, the fallback renderer shows the URL instead of the command value. The guidance now excludes these buttons from the command-present check, so the "You can type the command shown above manually" instruction is only shown when a command is actually visible as copyable text in the fallback output. (4bcf0a59a6)
  • P3 — document command/callback fallback visibility: Added a "Button value fallback visibility" subsection under "Degradation rules" in docs/plugins/message-presentation.md documenting which button value types are rendered as copyable text (action.type === "command") vs. kept private (callback, legacy value, select option values). Channel adapters that add manual-command guidance are advised to derive the command-present check from the same source the fallback renderer uses.
  • P2 — core delivery path command guidance preservation (0e0fea4d3f): renderFeishuPresentationPayload now sets a hasRenderedCommandAction marker in channelData.feishu when a command button would be rendered in fallback text. The sendPayload comment-target branch falls back to this marker when core renderPresentationForDelivery has already stripped the presentation field before calling sendPayload. This ensures the Feishu comment guidance still appears for normal core delivery (not just direct sendPayload calls). Regression test added covering the stripped-presentation + channelData-marker path (outbound.test.ts).
  • P1 — keep hasRenderedCommandAction plugin-local (4f6fc55b41): Per ClawSweeper review, moved hasRenderedCommandAction out of the public plugin SDK (src/plugin-sdk/interactive-runtime.ts → -1 export) and into extensions/feishu/src/outbound.ts as a local helper (~25 lines). Reverted the SDK surface budget bump (scripts/plugin-sdk-surface-report.mjs: 10401→10400, 5220→5219). Removed the now-dead exported function from src/interactive/payload.ts (-29 lines). The shared fallback renderer in renderMessagePresentationFallbackText already inlines the same command-visibility logic; a local helper is sufficient for the single Feishu call site. No public API contract burden.

Verification

  • pnpm build — build clean (590s, all 116 plugins compiled, plugin SDK boundary pass)
  • pnpm test extensions/feishu/src/outbound.test.ts src/interactive/payload.test.ts — 46 + 17 = 63 tests passed
  • pnpm tsgo:prod — production types clean
  • pnpm check:test-types — test types clean
  • pnpm test:extensions:package-boundary:compile — 116/116 plugins compiled
  • node_modules/.bin/oxlint --quiet — no new lint errors
  • pnpm format:check — format clean on all changed files
  • node scripts/plugin-sdk-surface-report.mjs — SDK budget green (559 exports ≤ 10400 budget)

Evidence

Live Feishu E2E verification (2026-06-30)

Verified against a real Feishu production environment (appId: cli_aac89d4a6cba9ce1) with 7 button-type scenarios sent to a document comment thread via the actual replyComment API from extensions/feishu/src/drive.ts. Each message went through the PR's renderMessagePresentationFallbackText and hasRenderedCommandAction gate before delivery.

# Scenario Feishu client observation Result
1 command button (批准/拒绝) 批准: \/approve req_1 allow-once`` visible + guidance line shown
2 callback button (忽略) - 忽略 label-only, callback value ignore_123_secret NOT leaked + no guidance
3 legacy value button (批准(老版本)) - 批准(老版本) label-only, legacy value NOT leaked + no guidance
4 URL button - 查看文档: https://example.com/docs URL displayed correctly
5 URL + command URL overrides command value, command NOT exposed + no guidance
6 mixed buttons (cmd + callback + URL + disabled) command values visible with inline code, callback private, URL shown, guidance present
7 plain text (no buttons) plain text only, no guidance

Proof command:

node --import tsx /tmp/send-feishu-fallback-test.mjs

Proof output (all 7 sent with reply_ids):

测试1: command 按钮 → 已发送 reply_id=7657103407966080223
测试2: callback 按钮 → 已发送 reply_id=7657103417923374325
测试3: legacy value 按钮 → 已发送 reply_id=7657103426886667482
测试4: URL 按钮 → 已发送 reply_id=7657103435988421836
测试5: URL+command → 已发送 reply_id=7657103445505101046
测试6: 混合按钮 → 已发送 reply_id=7657103456179604683
测试7: 纯文本 → 已发送 reply_id=7657103466090826984

Screenshots:
image
image
image

@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram channel: feishu Channel integration: feishu size: S 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 triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 18, 2026
@clawsweeper

clawsweeper Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 2, 2026, 3:36 PM ET / 19:36 UTC.

Summary
The PR changes shared message-presentation fallback text to render non-disabled typed command buttons as copyable inline commands, adds Feishu document-comment guidance with a stripped-presentation marker, and updates tests and plugin docs.

PR surface: Source +61, Tests +148, Docs +21. Total +230 across 6 files.

Reproducibility: yes. Current main source and tests show command-valued Feishu comment buttons degrade to label-only fallback text; I did not run a live current-main Feishu repro in this read-only review.

Review metrics: 1 noteworthy metric.

  • Shared Fallback Renderer: 1 renderer changed. All channels that rely on renderMessagePresentationFallbackText inherit the new typed-command visibility semantics.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #69754
Summary: This PR is the open candidate fix for the canonical Feishu approval fallback clarity issue; adjacent Feishu card and approval-routing items are not replacements.

Members:

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

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

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

Mantis proof suggestion
A native Telegram Desktop recording can show the cross-channel visible fallback behavior after the latest privacy and marker updates. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis telegram desktop proof: verify latest head shows typed command fallback text and keeps callback, legacy, URL-overridden, and disabled values private or label-only.

Risk before merge

  • [P1] The shared renderer change makes typed command values visible in degraded plain text for every channel that uses renderMessagePresentationFallbackText, so maintainers should explicitly accept that cross-channel semantic before merge.
  • [P2] The linked Feishu approval UX issue covers broader Feishu approval fallback clarity than document comments, so maintainers should decide whether this PR closes it or leaves a narrower follow-up open.

Maintainer options:

  1. Accept Shared Command Fallback (recommended)
    Maintainers can intentionally accept that typed command actions become visible in shared fallback text while callback and legacy opaque values remain private.
  2. Narrow Visibility To Feishu
    If shared fallback command visibility is not desired, require a pre-merge change that keeps command text rendering only in the Feishu comment fallback path.
  3. Keep Broader Issue Open
    If the linked Feishu approval report still needs DM/native approval or config-hint guidance, merge this PR without closing that broader tracker or open a focused follow-up.

Next step before merge

  • No automated repair is appropriate; the remaining action is maintainer acceptance of the shared fallback semantic and linked-issue closure scope.

Security
Cleared: No concrete security or supply-chain regression was found; callback and legacy opaque values remain private and the PR does not touch dependencies, workflows, secrets, or package resolution.

Review details

Best possible solution:

Land the narrow fallback repair after maintainer acceptance of shared typed-command fallback visibility and a clear decision on whether the linked Feishu approval UX issue should close or keep a follow-up.

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

Yes. Current main source and tests show command-valued Feishu comment buttons degrade to label-only fallback text; I did not run a live current-main Feishu repro in this read-only review.

Is this the best way to solve the issue?

Yes, with maintainer acceptance. The shared fallback renderer is the maintainable layer for typed command fallback, while Feishu-only guidance and marker handling stay inside the Feishu plugin instead of expanding the SDK surface.

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: This is a bounded Feishu/shared fallback bugfix with approval-message usability impact and limited blast radius.
  • merge-risk: 🚨 compatibility: The PR changes shared plain-text fallback rendering semantics used by multiple channel plugins when native controls are unavailable or paired with fallback text.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (screenshot): The PR body supplies live Feishu reply IDs and inspected screenshots showing after-fix command fallback, callback/legacy privacy, URL override, mixed-button, disabled-button, and plain-text cases.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body supplies live Feishu reply IDs and inspected screenshots showing after-fix command fallback, callback/legacy privacy, URL override, mixed-button, disabled-button, and plain-text cases.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The PR body supplies live Feishu reply IDs and inspected screenshots showing after-fix command fallback, callback/legacy privacy, URL override, mixed-button, disabled-button, and plain-text cases.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. The PR changes shared fallback rendering used by Telegram-visible degraded button messages, so a short Telegram Desktop proof remains useful.
Evidence reviewed

PR surface:

Source +61, Tests +148, Docs +21. Total +230 across 6 files.

View PR surface stats
Area Files Added Removed Net
Source 2 71 10 +61
Tests 2 150 2 +148
Docs 2 21 0 +21
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 6 242 12 +230

What I checked:

  • Repository policy read: Root AGENTS.md plus the scoped docs and extensions guides were read; their plugin-boundary, docs, and compatibility-review rules informed this review. (AGENTS.md:1, a004e18b4bbd)
  • Current main drops command values: Current main renders button fallback as label-only unless a URL exists, so typed command actions are not copyable in degraded text. (src/interactive/payload.ts:528, a004e18b4bbd)
  • Current main Feishu comment fallback: Current main sends Feishu document-comment interactive payloads through text fallback and clears interactive/presentation/channelData before delivery. (extensions/feishu/src/outbound.ts:506, a004e18b4bbd)
  • Current main source repro test: The current Feishu test expects a comment-thread approval button with value /approve req_1 to render as only Review this\n\n- Approve. (extensions/feishu/src/outbound.test.ts:837, a004e18b4bbd)
  • PR head fallback semantics: At PR head, the shared fallback renderer only renders action.type === "command" values, skips disabled buttons, and leaves callback/legacy values label-only. (src/interactive/payload.ts:550, dce6aacac331)
  • PR head Feishu marker path: At PR head, Feishu keeps the command-present predicate plugin-local and carries a boolean fallbackHasCommand marker for core-rendered deliveries where presentation has been stripped. (extensions/feishu/src/outbound.ts:324, dce6aacac331)

Likely related people:

  • steipete: Authored the merged typed presentation command/callback contract that this fallback behavior builds on and contributed the latest PR-head tightening commit. (role: feature owner and recent reviewer; confidence: high; commits: d641126c1dd6, dce6aacac331; files: src/interactive/payload.ts, docs/plugins/message-presentation.md, extensions/feishu/src/outbound.ts)
  • vincentkoc: Feature-history and PR context tie this person to the shared interactive payload model and Feishu outbound runtime seam that this PR changes. (role: shared payload and Feishu runtime contributor; confidence: high; commits: 2161b46032e0, e4cc8cd97513; files: src/interactive/payload.ts, extensions/feishu/src/outbound.ts, extensions/feishu/src/outbound.test.ts)
  • wittam-01: Authored the merged Feishu document-comment routing support adjacent to the degraded comment-thread fallback path. (role: adjacent Feishu comment-surface contributor; confidence: medium; commits: 1b94e8ca14de, ce0ff42ff5ed; files: extensions/feishu/src/outbound.ts, extensions/feishu/src/outbound.test.ts, extensions/feishu/src/comment-target.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 proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jun 18, 2026
@clawsweeper
clawsweeper Bot temporarily deployed to qa-live-shared June 18, 2026 04:39 Inactive
@openclaw-mantis

openclaw-mantis Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Mantis Telegram Desktop Proof

Summary: Mantis captured native Telegram Desktop before/after GIFs showing the command button fallback text.

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-94385/run-27890243350-1/index.json

@xialonglee

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review
openclaw-mantis has submit the live proof

@clawsweeper

clawsweeper Bot commented Jun 18, 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:

@xuwei-xy

Copy link
Copy Markdown

This could be resolved by updating ui. I'll prepare a PR if that sounds good.

@xialonglee

Copy link
Copy Markdown
Contributor Author

@xuwei-xy thanks for the suggestion. A UI-only fix could work for the Feishu guidance part, but the shared renderMessagePresentationFallbackText change affects all channels (Telegram included, as Mantis proof shows). The P1 callback privacy issue and P2 overly broad guidance check apply regardless of the approach layer. Let's let the maintainers decide which direction they prefer — happy to collaborate if you open a comparison PR.

@xialonglee xialonglee changed the title fix(feishu): preserve button command values in fallback text and add Feishu comment guidance fix(feishu): preserve button command values in fallback text and add Feishu comment guidance with callback privacy 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 proof: sufficient ClawSweeper judged the real behavior proof convincing. status: 🔁 re-review loop A fresh ClawSweeper review was explicitly requested after the latest review. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. proof: sufficient ClawSweeper judged the real behavior proof convincing. status: 🔁 re-review loop A fresh ClawSweeper review was explicitly requested after the latest review. labels Jun 18, 2026
@xialonglee

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 18, 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 the rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. label Jun 21, 2026
@xialonglee
xialonglee force-pushed the fix/issue-69754-feishu-approval-fallback branch from 4bcf0a5 to 0628827 Compare June 30, 2026 07:18
@openclaw-barnacle openclaw-barnacle Bot added triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. and removed triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jun 30, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. 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 30, 2026
@xialonglee

Copy link
Copy Markdown
Contributor Author

Addressed both P2 findings from the latest ClawSweeper review:

  1. Disabled command buttonsrenderMessagePresentationFallbackText now skips command rendering for disabled buttons (label-only, same as callback/legacy). The hasRenderedCommandAction check in Feishu outbound also excludes disabled buttons.

  2. Guidance predicate — Extracted hasRenderedCommandAction into a shared exported function in src/interactive/payload.ts and exposed through the plugin SDK (interactive-runtime.ts). Feishu outbound.ts now calls this single shared predicate instead of an inline .some() chain, reducing duplication and keeping the fallback renderer + guidance gate in sync.

Changes: +33 / -14 across 3 files (payload.ts, outbound.ts, interactive-runtime.ts).

  • node scripts/run-vitest.mjs src/interactive/payload.test.ts extensions/feishu/src/outbound.test.ts — 17 + 45 = 62 tests passed
  • node_modules/.bin/oxlint — clean on all changed files
  • node_modules/.bin/tsgo --noEmit -p tsconfig.core.json / -p tsconfig.extensions.json — clean except pre-existing core errors

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 30, 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.

xialonglee and others added 13 commits July 2, 2026 12:31
…arrow Feishu interactive detection

- P1: Skip rendering action.type === "callback" values in
  renderMessagePresentationFallbackText to avoid leaking opaque
  channel/plugin data into user-visible text. Command and legacy
  values are still rendered.
- P2: Replace hasMessagePresentationBlocks/hasInteractiveReplyBlocks
  with isMessagePresentationInteractiveBlock so Feishu comment
  guidance only appears when the presentation actually contains
  buttons or selects, not for text-only blocks.
- Update tests: callback button now shows label-only; all 137 tests pass.
…u plugin as local helper

Keep the helper local to the only caller (Feishu outbound) instead of
adding a new public plugin SDK API contract. The shared fallback renderer
in renderMessagePresentationFallbackText already inlines the same
command-visibility logic; a local helper is sufficient for the Feishu
comment-thread guidance gate.
@steipete

steipete commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Maintainer pass complete; land-ready.

  • Tightened the Feishu-private rendered-command marker to a strict boolean and kept the visibility helper plugin-local; no public SDK expansion.
  • scripts/pr review-tests 94385 src/interactive/payload.test.ts extensions/feishu/src/outbound.test.ts passed, covering the shared fallback and full Feishu test project.
  • Fresh exact-head autoreview: clean, 0.86 confidence.
  • Live proof: seven production Feishu document-comment scenarios in the PR Evidence section; sibling-channel Mantis Telegram comparison passed.
  • Exact-head hosted CI is fully green on dce6aacac3313b4c872633a2b63a88f9b497e7a7.

No known proof gaps.

@steipete

steipete commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

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

Labels

channel: feishu Channel integration: feishu docs Improvements or additions to documentation mantis: telegram-visible-proof Mantis should capture Telegram visible proof. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. 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: 🦞 diamond lobster Very strong PR readiness with only minor 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.

Approval UX on Feishu needs clearer fallback guidance when interactive buttons are unavailable or approval degrades to text

3 participants