Skip to content

fix(lark): qualify card callback delivery and project truthful no-callback outcomes #4370

Description

@huangruiteng

Problem / 问题

A post-merge, packaged Goal Channel qualification exposed a distinct gap from #4366: a Card 2.0 operation request was created and read back successfully, the local card-action consumer was running, and the Lark app had the published card.action.trigger subscription, but no callback event was produced for the operator's click. The operation stayed awaiting confirmation until expiry, with no claim, dispatch, simulation outcome, or result-card receipt.

合并并升级后的真实 Goal Channel 验收暴露了一个与 #4366 不同的问题:操作卡已成功创建并读回,本机卡片回调 consumer 正常运行,Lark 应用也已发布 card.action.trigger 订阅;但用户点击后,开放平台事件日志没有产生任何卡片回调。操作一直停留在 awaiting confirmation,最终过期;没有 claim、dispatch、模拟执行结果或结果卡回执。

This means listener-process health is necessary but not sufficient evidence that the interaction is qualified. The current surface can look healthy while the only user interaction path is silent.

这说明“监听进程健康”不能等价于“真实交互链路已验收”;当前状态会在唯一用户交互路径静默失效时仍显示健康。

Deployment evidence / 部署证据

  • Qualified against packaged LoopX main revision 49f979b with paired CLI and macOS Desktop App.
  • The original operation card had provider-native create/readback evidence.
  • The callback listener was active and its event-bus counters showed zero received and zero dropped card-action events.
  • The published Lark application configuration contained the card.action.trigger subscription using long connection.
  • The provider event log for the interaction window contained the later IM text message but no card.action.trigger event.
  • The operation expired while still awaiting confirmation; no domain consumer ran and no financial action occurred.
  • The card uses a callback behavior plus a secondary confirm dialog. Evidence cannot distinguish between a client-side secondary-confirmation flow that was not finalized and a Lark client/platform delivery failure; it does prove the LoopX callback handler never received a finalized decision.

Required behavior / 验收要求

  • Separate local listener readiness from live callback qualification. Status should expose a typed state such as listener_ready_unqualified until one real callback and canonical readback succeed for the exact app/route.
  • Provide an explicit preflight/qualification command and receipt that checks published subscription, consumer identity, route binding, and one real callback round trip without granting domain execution authority.
  • Make the two-step confirmation UX explicit, or remove redundant secondary confirmation when the canonical protected gate already provides the required confirmation boundary.
  • When an awaiting-confirmation operation expires without a callback, project a truthful terminal expiry/timed-out result to the original card and the same Goal Channel. Do not execute, claim, rerun the worker/model, or blindly resend.
  • Preserve known-locator idempotency and recovery boundaries. If the original provider message exists, repair only presentation/readback; unknown provider outcome remains fail-closed.
  • Readback must use the exact configured bot profile and return typed invalid-argument details instead of a generic missing-receiver conclusion.
  • Product acceptance must use a fresh simulation-only operation after the fix: desktop and mobile click, callback captured, authenticated decision, exactly-once simulation receipt, original-card result patch/readback, and the same canonical state in CLI/managed Turn and Desktop.
  • Chinese and English operator copy must explain whether the click was received, whether execution started, and what the safe next action is.

Scope / 边界

This issue owns callback qualification, no-callback expiry projection, and interaction feedback. It does not grant live trading authority, does not add finance semantics to Core, and does not replace #4366 known-locator delivery recovery. A fresh operation must be deliberate; the expired card must never be replayed as authorization.

本 issue 只负责 callback 验收、无 callback 的过期投影和交互反馈;不授予实盘交易权限,不把 finance 语义放入 Core,也不替代 #4366 的 known-locator 投递恢复。任何新卡都必须是明确的新请求,已过期卡不得被重放为授权。

Related: #3786, #3964, #4275, #4366.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions