From ea2fee4825078364c2c3c6e37e2f1ea7720b6ddf Mon Sep 17 00:00:00 2001 From: thedancingdeveloper <306930456+thedancingdeveloper@users.noreply.github.com> Date: Mon, 31 Aug 2026 22:54:10 +0000 Subject: [PATCH 1/8] fix(web): constrain New-session button icon size (#489) The New-session button's inline SVG carries only a viewBox, so on desktop it fell back to the 300x150 replaced-element default and ballooned the button, dominating the sessions header. Add a top-level `.sessions-new-icon` sizing rule (the phone media block already restated this; the two are kept in sync). Fixes #489 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01N7eWQbHi8HyLyhaRA2piEn --- web/src/styles.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web/src/styles.css b/web/src/styles.css index db854e65..9ad16574 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -1294,6 +1294,12 @@ textarea { white-space: normal; } +/* Base sizing for the New-session button icon. Without this the inline SVG has + only a viewBox and falls back to the 300x150 replaced-element default on + desktop, ballooning the button (issue #489). The phone media block below + restates this; keep the two in sync. */ +.sessions-new-icon { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; } + /* `.board-field select` is shared with the denser filter-panel form below, whose 8px padding is the right call there; in the header it is what pushed Board's own Refresh cadence to 36px next to every 32px button beside it. From 059b1859b91d6d7cff6e6babef99f0ff87c683d0 Mon Sep 17 00:00:00 2001 From: thedancingdeveloper <306930456+thedancingdeveloper@users.noreply.github.com> Date: Mon, 31 Aug 2026 22:54:18 +0000 Subject: [PATCH 2/8] fix(web): render History replay as readable transcript (#490) History shipped the raw session log verbatim into a
, so replays were
a wall of ANSI escape codes, cursor moves and spinner carriage returns
instead of readable output. Add `toReadableTranscript` (strips OSC/CSI and
short escapes, resolves in-place CR/backspace redraws to their final frame,
drops stray control bytes) and route both live and archived replays through
it. Update the replay note copy and its assertion.

Fixes #490

Co-Authored-By: Claude Opus 4.8 
Claude-Session: https://claude.ai/code/session_01N7eWQbHi8HyLyhaRA2piEn
---
 web/src/History.tsx                     |  7 ++-
 web/src/__tests__/historyReplay.test.ts | 51 ++++++++++++++++
 web/src/__tests__/historyTruth.test.tsx |  2 +-
 web/src/historyReplay.ts                | 77 +++++++++++++++++++++++++
 4 files changed, 133 insertions(+), 4 deletions(-)
 create mode 100644 web/src/__tests__/historyReplay.test.ts
 create mode 100644 web/src/historyReplay.ts

diff --git a/web/src/History.tsx b/web/src/History.tsx
index 97453ce5..5bf776df 100644
--- a/web/src/History.tsx
+++ b/web/src/History.tsx
@@ -22,6 +22,7 @@ import {
   toggleHistoryPin,
 } from "./historyPins";
 import { readToolDraft, writeToolDraft } from "./toolDrafts";
+import { toReadableTranscript } from "./historyReplay";
 import { sessionsStore } from "./store";
 import { SafeSnippet } from "./SafeSnippet";
 import { onWake } from "./wakeCoordinator";
@@ -1038,8 +1039,8 @@ const History: Component = (props) => {
                       Replay preview
                       
{selectedIsLive() - ? "Tail view of the live session's raw terminal log." - : "Tail view of the archived raw terminal log."} + ? "Tail of the live session, rendered readable — escape codes resolved." + : "Tail of the archived session, rendered readable — escape codes resolved."}