DSH / Atlas
2026-09-10implementedfeaturearchived 2026-09-30

Symmetric message feedback submission

对称消息反馈提交

The assistant-message rating controls used different commit points. Like recorded a positive rating immediately, while Dislike opened the feedback dialog and recorded only after Submit. The asymmetry made an accidental Like durable before confirmation and prevented positive feedback from carrying the same optional category and description as negative feedback.

English

Problem

The assistant-message rating controls used different commit points. Like recorded a positive rating immediately, while Dislike opened the feedback dialog and recorded only after Submit. The asymmetry made an accidental Like durable before confirmation and prevented positive feedback from carrying the same optional category and description as negative feedback.

Decision

The feedback dialog and categories decision owns the shared form and durable taxonomy. Both unrecorded ratings open the shared feedback dialog and record only after Submit. A message FeedbackDialogTarget carries the selected positive or negative rating, and FeedbackSurface passes that rating with the dialog entry to MessageFeedbackController.rate. The action row reads the committed item before either action: clicking its current rating calls the injected retract operation, while clicking an absent or opposite rating opens the dialog. retract rechecks the committed rating inside the controller's serialized mutation queue and becomes a no-op after a concurrent change, so it cannot turn stale UI intent into a bare rating put. The dialog remains optional-input: submitting without a category or description records the selected rating and raises the acknowledgement toast; dismissing it records nothing.

Alternatives considered

Keep Like as an immediate action. This preserves one fewer click for positive feedback, but keeps two submission models beside each other and prevents positive reports from carrying context.

Require the dialog to retract a recorded rating. Retraction has no category or description to collect, and an extra confirmation would make the existing undo action less direct.

Create separate positive and negative forms. The fields, validation, failures, and acknowledgement are identical; carrying the rating in the existing target keeps one draft and submission lifecycle.

Consequences

Neither rating creates a feedback/message-put event until the user submits the dialog. Positive and negative records can both include a category and note, while clicking the active rating continues to create feedback/message-delete without opening the dialog. Unit coverage pins the shared action path and target routing, and the keyless Web scenarios submit both ratings through the real dialog before checking durable events and telemetry release.

中文

问题

助手消息的两个评分控件使用不同的提交时点。点赞会立即记录正面评分,点踩则先打开反馈弹窗,仅在用户提交后记录。这种不对称会让误触点赞在确认前就持久化,也让正面反馈无法携带与负面反馈相同的可选分类和描述。

决策

反馈弹窗与分类决策负责共用表单和持久化分类表。两种未记录的评分都打开共用反馈弹窗,并且只在提交后记录。消息 FeedbackDialogTarget 携带所选的 positive 或 negative 评分,FeedbackSurface 将该评分与弹窗条目一起传给 MessageFeedbackController.rate。动作行会在任一操作前读取已提交条目:点击当前评分会调用注入的 retract 操作,点击未记录或相反评分则打开弹窗。retract 会在控制器的串行变更队列内重新检查已提交评分,并在并发变更后变为无操作,因此不会把陈旧的 UI 意图转成裸评分 put。弹窗的输入仍可全部留空:不选分类也不填描述时提交会记录所选评分并弹出确认 toast;关闭弹窗不会记录任何内容。

考虑过的替代方案

保留点赞立即提交。 这能让正面反馈少一次点击,但会让并列的两个评分继续使用不同提交模式,也无法让正面反馈携带上下文。

撤回已记录评分也必须经过弹窗。 撤回没有需要收集的分类或描述,多一次确认会让现有撤销操作变得不够直接。

分别创建正面和负面表单。 两者的字段、校验、失败处理与确认完全相同;在现有目标中携带评分即可共用一套草稿与提交生命周期。

后果

用户提交弹窗前,两种评分都不会创建 feedback/message-put 事件。正面与负面记录都可以包含分类和备注,而点击当前评分仍会直接创建 feedback/message-delete,无需打开弹窗。单元测试固定共用动作路径与目标路由,无密钥 Web 场景则通过真实弹窗提交两种评分,再检查持久事件与遥测投递。