Bug Description
Telegram 的 ask_user 卡片按钮(单选/多选/Other…/Skip/Submit,即 aui~ wizard 回调)全部不可用:点任何按钮都弹「This question has expired.」。这是潜伏 bug,与问题是否真的过期无关——卡片刚渲染出来、问题仍处于 pending 时按钮就是死的。
根因是 runtime fence 守卫与 wizard 解析路径的契约错位:
- turn 创建 ask_user 时
CreatePending 会把 run 的 runtime fence 打到 user_input_requests.runtime_fencing_token(internal/agent/decision/input/service.go:164)。
- Telegram 按钮回调走 channel 进程内 DB 直连的
AdvanceInteraction(ctx 无 fence,internal/channel/adapters/telegram/telegram.go:737 → cmd/internal/channel/providers.go:125-131)。
GetRespondableUserInputRequest 的 NULL-token 分支要求 runtime_fencing_token IS NULL(db/postgres/queries/user_input.sql)。带 fence 的行对 unfenced 查询永远不可见 → ErrNotFound → Handled=false → 弹 expired(telegram.go:749-752)。
时间线:wizard 建于 #817(2026-07-16);次日 #800(07-17)给 GetRespondableUserInputRequest 加 fence 守卫并让 CreatePending 打 token;#865(07-28)/#960(08-06)使 durable runtime + decision parking 成为默认后,所有 turn 创建的 ask_user 行都是 fenced,该路径自此全灭。web 不受影响:web 作答走 WS user_input_response → RouteDecisionResponse → DecisionContinuationContext 携带 fence(internal/handlers/local_channel.go:1856-1920),所以此前 QA 没有暴露。
Steps to Reproduce
- bot 接 Telegram,触发
ask_user 产生带按钮的卡片。
- 立即点任意按钮(单选选项 / Other… / Skip)。
- 弹窗提示
This question has expired.,卡片无法作答。
Error Messages / Logs
# Telegram 弹窗
This question has expired.
# 无服务端报错日志:AdvanceInteraction 对查不到的行返回 Handled=false,属静默路径
Version
main(2026-09-03;#800 之后所有版本)
Channel
Telegram
Additional Context
Bug Description
Telegram 的 ask_user 卡片按钮(单选/多选/Other…/Skip/Submit,即
aui~wizard 回调)全部不可用:点任何按钮都弹「This question has expired.」。这是潜伏 bug,与问题是否真的过期无关——卡片刚渲染出来、问题仍处于 pending 时按钮就是死的。根因是 runtime fence 守卫与 wizard 解析路径的契约错位:
CreatePending会把 run 的 runtime fence 打到user_input_requests.runtime_fencing_token(internal/agent/decision/input/service.go:164)。AdvanceInteraction(ctx 无 fence,internal/channel/adapters/telegram/telegram.go:737→cmd/internal/channel/providers.go:125-131)。GetRespondableUserInputRequest的 NULL-token 分支要求runtime_fencing_token IS NULL(db/postgres/queries/user_input.sql)。带 fence 的行对 unfenced 查询永远不可见 →ErrNotFound→Handled=false→ 弹 expired(telegram.go:749-752)。时间线:wizard 建于 #817(2026-07-16);次日 #800(07-17)给
GetRespondableUserInputRequest加 fence 守卫并让CreatePending打 token;#865(07-28)/#960(08-06)使 durable runtime + decision parking 成为默认后,所有 turn 创建的 ask_user 行都是 fenced,该路径自此全灭。web 不受影响:web 作答走 WSuser_input_response→RouteDecisionResponse→DecisionContinuationContext携带 fence(internal/handlers/local_channel.go:1856-1920),所以此前 QA 没有暴露。Steps to Reproduce
ask_user产生带按钮的卡片。This question has expired.,卡片无法作答。Error Messages / Logs
Version
main(2026-09-03;#800 之后所有版本)
Channel
Telegram
Additional Context
user_input_requests行,应为status='pending'且runtime_fencing_token IS NOT NULL(证明未被 supersede,纯粹是查询不可见)。AdvanceInteraction只是 UI 中间态(选项勾选/翻页),不直接终态化请求,不该吃 runtime fence 的 respondable 守卫——resolve 应放宽(例如 wizard 路径改用不带 fence 分支的读取 + 状态校验);最终 Submit 仍走 server 侧 fenced 的RespondUserInput路径,权限语义不变。