Remove the steering interjection caption
移除 steering(中途引导)插话标注
The [context-source and steer marks decision](../feature/2026-08-04-web-context-source-and-steer-marks.md) captioned every durable and pending steering bubble with `插话` / `Interjection` so the transcript could say which right-aligned bubble interrupted a running turn. The caption repeats what the flow already shows: a steering bubble sits mid-turn, between the assistant content it interrupted, while a turn-opening pr
English
Problem
The context-source and steer marks decision captioned every durable and pending steering bubble with 插话 / Interjection so the transcript could say which right-aligned bubble interrupted a running turn. The caption repeats what the flow already shows: a steering bubble sits mid-turn, between the assistant content it interrupted, while a turn-opening prompt sits at a turn boundary. A permanent line of tertiary text above every steer bubble buys no reading a position-aware reader does not already have, and it is the only chrome any user-style bubble carries, so it also breaks the otherwise uniform right-aligned rhythm.
Decision
Steering renders exactly as a user bubble. UserStyleBubble has no steering flag, the message.steering locale key and the .steeringMark style are deleted, and PendingSteeringBubble and UserMessageNodeView pass only content and actions. A mid-turn steer is recognizable by its position inside the running turn's flow, and by nothing else.
The runtime distinction is untouched. SteeringMessageNode projection from durable agent/inbox/spliced history, the data-pending-steering attribute, and the pending-to-durable hand-off all remain: the pending lifecycle needs the node identity regardless of presentation, and tests still locate pending bubbles through the attribute.
This partially supersedes the steering clause of the context-source and steer marks decision; its context-source and recall naming stays current. The caption has flipped before: the archived no-steer decision removed it while the composer could not steer, and the 2026-08-04 decision reintroduced it after the composer gained a Steer gesture. This removal does not revisit the gesture — steering entry, the Queue dock's steer-send action, and the pending lifecycle keep their owners — it judges only that the transcript need not name the result.
Alternatives considered
Keep the caption. It is the status quo and cheap to keep, but it decorates every steer bubble forever to encode a fact the bubble's position already states. Chrome that carries no information a reader lacks is removed, not maintained.
Remove the SteeringMessageNode distinction too. The node kind is derived from durable inbox history and drives the pending-to-durable hand-off; it is a replay fact, not presentation. Folding it into UserMessageNode would change projection behavior for no UI gain.
Distinguish steering with quieter chrome (tint, indent, hover-only label). Any replacement re-raises the same question with a weaker vocabulary. The distinction the transcript needs is positional and already visible; adding subtler decoration keeps the cost and loses the one virtue the text caption had, being explicit.
Testing
packages/client/ui-conversationjsdom coverage pins the plain bubble: the pending hand-off test locates pending bubbles bydata-pending-steeringand asserts the single-bubble hand-off without any caption, and the MessageItem steering arm asserts copy-without-branch on an uncaptioned bubble.- The keyless assembled-Web goldens (
steering/mid-steer,steering/settled,plan-review/approved) replay the unchanged session fixtures with no caption text.
Consequences
- A replayed transcript no longer names steering: a reader infers a mid-turn interjection from its position inside the turn. That inference is weaker than an explicit label for a reader skimming turn boundaries; the decision accepts this.
- A pending steer bubble is visually identical to an ordinary sent bubble until admission; only its missing clock time differs.
- Reintroducing steering chrome of any form requires a new product decision superseding this note.
中文
问题
上下文来源与 steer 标识决策给每个持久与待处理的 steering 气泡加上了 插话 / Interjection 标注,让 transcript(文本记录)能说明哪条右对齐气泡打断了正在运行的轮次。这个标注重复了消息流已经呈现的事实:steering 气泡位于轮次中途、夹在被它打断的助手内容之间,而开轮提示位于轮次边界。在每个 steer 气泡上方常驻一行三级文字,并没有让一个能看到位置的读者多读出任何信息,而且它是所有用户样式气泡中唯一带装饰的,还破坏了原本统一的右对齐节奏。
决策
steering 完全按用户气泡渲染。UserStyleBubble 不再有 steering 标志,message.steering locale 键与 .steeringMark 样式已删除,PendingSteeringBubble 与 UserMessageNodeView 只传内容与操作。轮次中途的 steer 只能靠它在运行轮次消息流中的位置辨认,除此之外没有任何标识。
运行时的区分保持不变。从持久 agent/inbox/spliced 历史投影 SteeringMessageNode、data-pending-steering 属性、待处理到持久的交接全部保留:待处理生命周期无论呈现如何都需要节点身份,测试也仍通过该属性定位待处理气泡。
本决策部分取代上下文来源与 steer 标识决策中的 steering 条款;其上下文来源与召回命名仍然有效。这个标注此前已经翻转过一次:已归档的取消 steer 装饰决策在 composer 无法 steer 时移除了它,2026-08-04 的决策在 composer 获得 Steer 手势后把它加了回来。本次移除不重议手势本身——steering 入口、Queue dock 的插话发送操作、待处理生命周期各归其主——只判定 transcript 不需要为其结果命名。
考虑过的替代方案
保留标注。 它是现状,维持成本低,但它永久装饰每个 steer 气泡,只为编码气泡位置已经陈述的事实。不承载读者缺少的信息的装饰应当删除,而不是维护。
连 SteeringMessageNode 区分一起删。 节点类型派生自持久 inbox 历史,驱动待处理到持久的交接;它是回放事实,不是呈现。把它并入 UserMessageNode 会改变投影行为,却没有任何 UI 收益。
换更安静的装饰(底色、缩进、悬停标签)。 任何替代装饰都会用更弱的表达重新提出同一个问题。transcript 需要的区分是位置性的、已经可见的;换成更含蓄的装饰保留了成本,却丢掉了文字标注唯一的优点,就是明确。
测试
packages/client/ui-conversation的 jsdom 覆盖固定了纯气泡行为:待处理交接测试通过data-pending-steering定位待处理气泡,在没有任何标注的前提下断言单气泡交接;MessageItem 的 steering 分支在无标注气泡上断言可复制且无分支操作。- 无密钥的组装 Web goldens(
steering/mid-steer、steering/settled、plan-review/approved)用未变的会话 fixture 回放,不含标注文字。
后果
- 回放的 transcript 不再为 steering 命名:读者靠消息在轮次中的位置推断这是一次中途插话。对快速扫读轮次边界的读者,这个推断弱于显式标签;本决策接受这一代价。
- 待处理的 steer 气泡在被准入前与普通已发送气泡在视觉上完全一致,仅缺少时间戳。
- 重新引入任何形式的 steering 装饰都需要一个取代本 note 的新产品决策。