From f68bae3a4d943c12935c4b950f97cc55c1a75156 Mon Sep 17 00:00:00 2001 From: Raghav Chari Date: Sun, 23 Aug 2026 21:49:36 -0400 Subject: [PATCH] =?UTF-8?q?fix(timeline):=20lone=20thinking=20is=20dot-onl?= =?UTF-8?q?y=20=E2=80=94=20every=20line=20must=20end=20at=20both=20dots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lone Thinking is first+last+running with a single dot. Both dangles (dot→bottom and 0→dot) leave one open end — every spine must end AT a dot at both ends, so a single dot has no line. Widget lab showed the cap still reads as line starting at thin air. Revert to 0px (PR 242) for lone, keep multi-step caps/bridges. Update Rule 6 docs. --- .../pages/session/timeline/thought-rail.tsx | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/packages/app/src/pages/session/timeline/thought-rail.tsx b/packages/app/src/pages/session/timeline/thought-rail.tsx index ef4d0a93e..8ab9769c9 100644 --- a/packages/app/src/pages/session/timeline/thought-rail.tsx +++ b/packages/app/src/pages/session/timeline/thought-rail.tsx @@ -58,9 +58,10 @@ // dot is decoration, not a sequence). A lone RUNNING step DOES rail — // its dot is the turn's only "working" signal (card sig / Livedot are // gone) and first steps are often the longest, so waiting for step two -// left the opening with no status. The lone live dot itself carries no -// line (first && last → 0px) so completion is just "dot fills" with no -// retraction. +// left the opening with no status. The lone live dot draws no line +// (0px) — every spine must end at a dot, so a single dot has no dangling +// half-spine above or below. A one-step completion still reads as "dot +// fills". // // Other implementation: the harness StepFrame rail on PR #216 slices by SDK // step-start/step-finish markers instead of assistant-part turns — different @@ -108,6 +109,12 @@ export function ThoughtRail(props: { const isRunning = () => props.last && props.running // Rule 3 — cap at dot centre; Rule 2 — NEG_STEP_GAP bridges the pt-3 gap. const dotCentre = DOT_TOP + NODE / 2 + // Lone running (Thinking before the first assistant part) is a single dot + // with no spine — every line must end AT a dot at both ends, like Claude + // Code. A lone dot has no line, so a one-step completion is just "dot + // fills" with no dangling half-spine above or below. The widget lab + // showed both dangles (dot→bottom, 0→dot) still leave one open end. + const isLoneRunning = () => props.first && props.last && props.running return ( <>