From 65027490c2bed261c07813111f4eb33a074fb0d1 Mon Sep 17 00:00:00 2001 From: Suleiman Shahbari Date: Tue, 11 Aug 2026 02:20:39 +0300 Subject: [PATCH] =?UTF-8?q?Session=20log:=20wash=20the=20rows=20worth=20fi?= =?UTF-8?q?nding=20=E2=80=94=20your=20turns,=20failures,=20the=20landing?= =?UTF-8?q?=20(fix=20#1508)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A background tint across the whole line, findable from the scrollbar's distance where a coloured badge word is not. Blue for the reader's own turns, red for failures, green for a clean end / ready-for-merge, at /10 alpha; the bulk of the log stays plain canvas so the washed rows actually stand out. Co-Authored-By: Claude Fable 5 --- .../components/EventList.test.tsx | 31 +++++++++++++++++++ .../components/EventList.tsx | 18 ++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) 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 && (