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
#1381 landed the bar's horizontal position; this branch decides when it is
drawn. The e2e keeps both scenarios and the golden carries both palettes'
pointer-state readings alongside the new edge-offset lines.
Review findings from the first round:
- ui-settings renders its full-viewport panel as a fixed-position DESCENDANT
of the sidebar column, so `pointerleave` never fires when the pointer moves
onto it and the bars stayed drawn after it closed. Leaving is now decided
against the column's box from a document-level pointermove that exists only
while the bars are drawn; the element's own leave stays for the pointer that
leaves the window.
- The rebind gate judges the rule rather than each declaration, so a pair that
mixes `transparent` with an l2 hover no longer passes, and the elevation
half compares whole values instead of token shape.
- Hiding no longer exempts a sheet from the elevated-surface rebind check.
- The e2e polls the reveal before reading a colour for the golden, and pins
that a pointerless scroll draws no thumb.
The session list overflows after a handful of sessions, and its scrollbar
was drawn permanently in a column that is at rest most of the time.
SidebarRoot now tracks the pointer over the whole column and rebinds
ui-theme's scrollbar indirection pair to `transparent` while it is
outside, keeping the thumb for 2s after the pointer leaves so it does not
blink out on the way past. Rebinding colour leaves the list's
`scrollbar-gutter: stable` reservation in force, so revealing the bar
moves no row.
ui-theme's gate now states the widened contract: a rebind targets an -l2
token pair or `transparent`, and nothing else.
session-title already registers a title projection unit; /resume now
reads it instead of scanning logs: live rows from the registry
snapshot, persisted rows from the durable checkpoint row
(cachedSnapshot, zero I/O), and only rows without a usable checkpoint
pay a coldSnapshot — checkpoint plus readFrom tail, written back so the
next scan is metadata-only. Cold reads are bounded by the new
resumeScanConcurrency config; compositions without the cache fall back
to the bounded readTitleSnapshots batch. The TUI overlay mounts the
projection registry, storage, and projection-cache rows over the same
storages root the web surface uses, so checkpoints serve both.
Making `.sources` a scroll container turned its `padding-left` from spacing
into a correctness constraint. A scroll container clips inline-start overflow
with no way to scroll it back, and `::marker` is right-aligned to the content
edge, so past nine sources the markers rendered as `0.` and `1.` where `10.`
and `11.` belonged.
`searchMaxResults` is an unbounded positive integer, so size the padding in
`em` against the list's own font to hold a three-digit marker. The browser e2e
measures a `999. ` marker in that inherited font and requires the computed
padding to be at least that wide, pinning the room against the widest marker
rather than one fixture's source count.
PR #1003 re-recorded this golden from a base that predated PR #1150, which
disables the branch control on any message that is not a completed turn's
tail. Both landed on master, whose CI skips the snapshot lane, so the
conflict only surfaces on PRs. The first message's control is now disabled
with its explanatory text.