Every logged non-user user/message collapsed into one identical
「上下文注入」 row, and mid-turn steering rendered in exactly the bubble a
turn-opening prompt uses, so the transcript could not say what had been
added or which message interrupted a running turn.
TranscriptAdapter and the history fold now attach a provenance view to
each context node, computed by contextProvenance() from the durable
source alone: a role (inject, or recall for a cross-session snapshot)
and a producer name read out of the log — instruction paths for
workspace-instructions, session titles for session-reference, the plugin
id for a plugin source, and the bare kind for any other. No client-side
table of producer names, so a renamed or newly mounted producer stays
identifiable without a client release and a foreign log projects like a
live one. ContextInjectionRow titles itself from the role and shows the
name beside it; MessageItem captions durable and pending steering
bubbles.
The caption reverses one clause of the no-interjection-chrome decision,
which removed it because the composer could not steer; composer steering
shipped afterwards without amending that note, so this change supplies
the product decision its reintroduction clause required and corrects the
stale facts left in it.
Fixes#1291
Derive turn wall time from adjacent logged timestamps (no new session
events): the actions-owning assistant footer gains a localized
"Ran for {duration}" label, and the running TurnStatus label gains a
live elapsed clock anchored to the same logged trigger so a mid-turn
reload keeps the real elapsed time. Message time chrome is now
hover-revealed on hover-capable devices, keeping icons visible and
layout stable.
Replace the WebBlock search card's head/tail collapse and expand button
with a fixed-height scroll container that lists every source the tool
returned. The model-facing side is unchanged: the seam still caps sources
at searchMaxResults and the truncated indicator stays, so model-visible
and frontend-visible sources remain identical.
Remove CHAT_WEB_MAX_SOURCES and DEFAULT_WEB_MAX_SOURCES: with scroll, the
chat row and details panel show the same full list.
The mount fixture always listed the session, so the case named "no list
summary" actually exercised a row proving non-blank. An omitSummaryRow
option drops the row, and the three cases now pin blank:false, an absent
row, and the summary-proven blank open.
The mount helper's 4th positional argument becomes an options object so a
test can set the session list row's blank flag independently of the
conversation snapshot's; the two new cases cover both branches of the
settling condition.