diff --git a/packages/framework-dashboard/components/EventList.test.tsx b/packages/framework-dashboard/components/EventList.test.tsx
index 769dc786..75f2ed16 100644
--- a/packages/framework-dashboard/components/EventList.test.tsx
+++ b/packages/framework-dashboard/components/EventList.test.tsx
@@ -271,3 +271,34 @@ describe('EventList inline browser rows (#1455 item 6b)', () => {
expect(screen.getByText('browser').className).toContain('text-primary')
})
})
+
+// The background wash (#1508): a tint across the whole line for the rows the eye hunts for —
+// the reader's own turns, failures, the clean landing — while the bulk of the log stays plain.
+describe('EventList row wash (#1508)', () => {
+ test("the reader's own turn gets the blue wash", () => {
+ const { container } = render(
+ ,
+ )
+ expect(container.querySelector('[class*="bg-info/10"]')).toBeTruthy()
+ })
+
+ test('a failure gets the red wash', () => {
+ const { container } = render()
+ expect(container.querySelector('[class*="bg-danger/10"]')).toBeTruthy()
+ })
+
+ test('a clean end gets the green wash; a stopped one gets none', () => {
+ const { container } = render()
+ expect(container.querySelector('[class*="bg-success/10"]')).toBeTruthy()
+ cleanup()
+ const { container: stopped } = render()
+ expect(stopped.querySelector('[class*="bg-info"], [class*="bg-danger"], [class*="bg-success"]')).toBeNull()
+ })
+
+ test("an agent reply stays plain canvas — the log's bulk must not shout", () => {
+ const { container } = render(
+ ,
+ )
+ expect(container.querySelector('[class*="bg-info"], [class*="bg-danger"], [class*="bg-success"]')).toBeNull()
+ })
+})
diff --git a/packages/framework-dashboard/components/EventList.tsx b/packages/framework-dashboard/components/EventList.tsx
index 3597d695..3ce66677 100644
--- a/packages/framework-dashboard/components/EventList.tsx
+++ b/packages/framework-dashboard/components/EventList.tsx
@@ -118,6 +118,20 @@ function badgeTone(e: FrameworkEvent): string {
return ''
}
+/**
+ * The row's BACKGROUND wash (#1508), the layer above {@link badgeTone}'s markers: a tint across
+ * the whole line, findable from the scrollbar's distance where a coloured badge word is not.
+ * Only the rows the eye actually hunts for get one — the reader's own turns (the log's natural
+ * chapter marks), failures, and the run landing cleanly — and at a whisper of alpha, so the
+ * text keeps the contrast and the bulk of the log stays plain canvas.
+ */
+function rowWash(e: FrameworkEvent): string {
+ if (isFailure(e)) return 'bg-danger/10'
+ if (e.kind === 'driver' && e.event.type === 'start') return 'bg-info/10'
+ if ((e.kind === 'end' && e.ok) || e.kind === 'ready-for-merge') return 'bg-success/10'
+ return ''
+}
+
/**
* Hoist the run's first prompt to the top of the log (#1170).
*
@@ -292,7 +306,9 @@ export function EventList({
const chunkHead = !prev || rowGroup(prev) !== rowGroup(e)
const at = receivedAt(e)
return (
-
+ // Every row carries the same -mx/px pair so a washed row's band and a plain row's
+ // text share the exact same columns; only the background differs.
+
{/* Fixed-width badge column so the text lines up whether or not this row repeats the badge. Wide enough for the longest common label ("system prompt") to sit on one line. */}
{chunkHead && (