Files
deepseek-harness/.agents/notes/implemented/simplification/2026-07-31-web-ui-no-steer-entry-or-interjection-chrome.md
T
creatixchu ccd27f3775 fix(web): address the second review round on context provenance
- An empty replacement catalog is a real catalog: `renderCatalogUpdate()`
  publishes zero entries when the last skill disappears, and falling back
  would hide that every earlier name was retired.
- The opaque fallback keeps a `form` declaration this version cannot present.
  It is the one place a newer or foreign log's declared shape would otherwise
  vanish from the UI entirely, since the row marker is also absent there.
- An instruction change with an unrecognized `action` disqualifies the record.
  The action decides the word the row shows, so an unknown one would be
  presented as loaded or updated.
- The catalog list bounds itself and reports the withheld count. Entry count
  is unbounded and the scrollport bounds height, not node count.
- A catalog message keeps content blocks this version does not know, instead
  of dropping model-visible content the extensible union may carry.
- `core.md` defines `ContextFormed`, the interface actually carrying the
  optional field, beside `ContextForm`.
- The superseded-in-part bullet states the affected clauses as one rule rather
  than enumerating them; two rounds of enumeration each missed some, which is
  the shape being fragile rather than the list being wrong.
- The note records the one migration case that does not self-heal: an
  old-format catalog as the only one, with an empty current view, leaves a
  stale catalog nothing replaces.
2026-08-05 16:51:01 +08:00

3.4 KiB

Agent Note: Web UI drops steer entry and interjection chrome

Status: implemented

English | 中文

Problem

Mid-turn steering is a host/agent-loop capability (mode:'steer', durable steering/message). The Web product already locked the composer while a turn runs and never shipped a queue/steer menu, yet the client still threaded 'queue' | 'steer' through the input machine, conversation.send, and locale keys, and rendered consumed steering as a badged 「插话」/「Interjection」 bubble. That left a half-built UI surface: an unused submit mode, a product label for a gesture users cannot perform, and e2e goldens that pinned chrome the product does not own.

Decision

Keep host and runtime steering intact. Remove only the Web UI entry and chrome:

  • InputMachine / SessionInput / InputActions.submit / hub defaultSink are queue-only; they always call session.prompt(..., 'queue').
  • ConversationService.send(text) drops its mode argument and always queues.
  • MessageItem's steering arm still folds durable steering/message content into a plain right-aligned bubble (no badge, no user IconActions) so external/host steers stay visible on replay.
  • Delete message.steering locale strings and the unused badge CSS.
  • The web steering e2e still POSTs mode:'steer' over /api/session.prompt and asserts durable + model-visible obedience; it no longer expects interjection chrome. Update web input machine note fact lines to match.

Alternatives considered

Delete host steering entirely. Out of scope; the user asked only for Web UI display and entry. Agent-loop drain, session events, and the wire mode remain load-bearing for ACP/TUI/automation.

Hide steering/message from the transcript. Would lie on replay when an external client steers; rejected in favor of a plain bubble.

Keep the mode parameter but only ever pass 'queue'. Leaves dead API surface and tests that invent 'steer' paths the composer cannot reach.

Consequences

  • Superseded in part. Every clause below about the steer ENTRY, the queue/steer mode union, the interjection caption, its locale strings, and the goldens that pinned their absence no longer describes master — in the Decision that is bullets 1 and 3 through 5, and in the consequences bullets 1 and 3. Composer steering shipped afterwards, and the context-source and steer marks decision then supplied the product decision this note's reintroduction clause required. What still holds: host steering ownership, ConversationService.send's queue-only contract, and the rejection of hiding steering/message from the transcript.
  • Web users cannot steer from the composer or ctx.conversation.send; stop/cancel and Queue remain the only mid-turn controls.
  • Host-wire and non-Web clients can still steer; the Web client shows those messages without labeling them as interjections.
  • Reintroducing a dedicated steer UI would need a new product decision; do not revive the mode union or badge without one.

Testing

  • packages/client/ui-conversation unit/jsdom coverage: input machine enter/sink, ConversationService routing, MessageItem steering arm (no 「插话」), InputBar submit.
  • apps/web/tests/steering.e2e.ts keyless replay plus updated settled.expected.md (steer text without badge).