Skip to content

feat(chat): the timeline shows the work instead of hiding it behind three clicks - #13

Merged
leonardoxr merged 3 commits into
main-xavierfrom
feat/timeline-shows-the-work
Aug 19, 2026
Merged

feat(chat): the timeline shows the work instead of hiding it behind three clicks#13
leonardoxr merged 3 commits into
main-xavierfrom
feat/timeline-shows-the-work

Conversation

@leonardoxr

@leonardoxr leonardoxr commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Problem

#5 made the omp payload rich — thinking, per-tool output, inline diffs, tool identity. Using it, the chat still read almost exactly like before. The reason was not the data: it was the timeline's default posture.

  • MAX_VISIBLE_WORK_LOG_ENTRIES = 1 condensed every work group to its last row, including while the turn was still running.
  • deriveTurnFolds hid the whole turn behind Worked for Xs the instant it settled.
  • Thinking arrived as a one-line clickable stub; output and diffs lived in the row's disclosure.

Net effect: reading what the agent actually did took three clicks (open the fold → open +N previous → open the row). My own verification screenshots for #5 needed exactly those three clicks to prove the feature existed — a signal I ignored at the time.

Change

Five adjustments to what is visible by default. The model becomes: the current turn is fully visible; history folds away.

  1. Thinking renders as prose in the flow, not as a tool row — its own timeline row (markdown, dimmed, italic), clamped to three lines with a Show thinking disclosure. Tool grouping breaks around it.
  2. The current turn shows every work row. Condensation applies only to turns that are neither running nor the latest.
  3. Short tool output (≤600 chars, ≤8 lines) renders under its row without a click. Larger output stays behind the disclosure.
  4. Small diffs (≤2 files, ≤80 lines) render inline; bigger ones stay lazy so shiki is not paid for off-screen work.
  5. The latest turn's fold starts open, keeping its duration header while leaving content on screen. The toggle set now records a deviation from each fold's default, so one set both opens an old turn and closes the current one.

The default-open rule deliberately does not apply in the window between sending a message and the server creating its turn: latestTurn still points at the previous settled turn there, so expanding it would pop content open and snap it shut a moment later. An existing test guards that window; it caught this during development.

Mobile gets the same five behaviors adapted to its feed, including height estimates so rows do not jump, and a plain +/- diff renderer (no new dependency). Expansion state lives in the feed's map rather than row-local state because that list recycles rows.

Before / after

Same thread, same data — only the default posture changed.

Before — thinking as one-line stubs, tool rows with no payload, output and diff behind the disclosure:

Timeline before

After — thinking as clamped prose, read output inline, colored diff inline, every tool row of the current turn present:

Timeline after

Another thread — two thinking blocks reading as prose, intent-titled tool rows, subagent CTA, all with zero clicks:

Thinking inline

Verification

  • 131 web tests (timeline logic + rows + session-logic) and 21 mobile threadActivity tests green; typecheck clean on web and mobile. New cases cover: thinking lifted out of tool groups, current turn uncondensed vs. older turns condensed, the XOR fold toggle, the inline output/diff thresholds, and the post-send no-flash window.
  • Driven in a real browser against existing omp threads (no model calls spent): thinking, per-tool output and a colored inline diff all visible with zero clicks.

Perf notes: the condensation that protects long threads is unchanged for history — folds still hide older turns entirely, and LegendList still virtualizes. Inline diffs are threshold-gated so shiki stays lazy for anything substantial. No new animation; the thinking clamp is a static class swap.

Known, not fixed here: rows persisted before #5's title fix still read Tool because the summary was written at ingestion time. Deriving the title in the projection would repair old threads retroactively — separate change if wanted.

Built with Claude Fable 5 on Oh My Pi.

…hree clicks

The rich-chat work made the payload rich but left the timeline's default
posture unchanged, so it still read almost like before: thinking was a
one-line stub, tool output and diffs sat three clicks deep (open the turn
fold, open '+N previous', open the row), and a settled turn collapsed to
'Worked for Xs' the instant it finished. The data was there; the UI just
never showed it.

Five changes to what is visible by default:

- Thinking renders as prose in the flow, not as a tool row. Reasoning
  entries become their own timeline row (markdown, dimmed, italic), clamped
  to three lines with a 'Show thinking' disclosure, and tool grouping breaks
  around them.
- The current turn shows every work row. Condensation to one row plus
  '+N previous' now applies only to turns that are neither running nor the
  latest, so you watch the work land and it stays readable afterwards.
- Short tool output (<=600 chars, <=8 lines) renders under its row without
  a click; anything larger stays behind the disclosure.
- Small diffs (<=2 files, <=80 lines) render inline for the same reason;
  bigger ones stay lazy so shiki is not paid for off-screen work.
- The latest turn's fold starts open, keeping its duration header while
  leaving the content on screen. The toggle set now records a deviation
  from each fold's default, so one set both opens an old turn and closes
  the current one. Turns older than the latest still fold away entirely.

The default-open rule deliberately does not apply in the window between
sending a message and the server creating its turn: latestTurn still points
at the previous, settled turn there, and expanding it would pop content open
and snap it shut a moment later.

Mobile gets the same five behaviors adapted to its feed (thinking entry,
current-turn passthrough, inline output/diff blocks with a plain +/- diff
renderer, XOR fold toggle), including height estimates so the rows do not
jump. Mobile expansion state lives in the feed's map rather than row-local
state because its list recycles rows.

Verified against real omp threads in the browser: thinking, per-tool output
and a colored inline diff are all visible with zero clicks.

Built with Claude Fable 5 on Oh My Pi.
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels Aug 19, 2026
…shows-the-work

The inline output and inline diff this branch added read
`data.rawOutput.fullText` and `data.diffs` off the activity payload. On
main-xavier those fields no longer reach a client: #13's base slimmed the
wire and serves output plus diffs from `orchestration.getActivityOutput`
for the one row a user expands, against a measured transfer budget.

So the two default-visible payload behaviors are dropped rather than
reinstated. Web rows keep the on-demand fetch; the row's disclosure holds
output and diffs as it does on main-xavier. Mobile's inline plumbing —
`inlineOutput`, `inlineDiffs`, the `+`/`-` diff renderer and the height
math that sized it — is removed outright: it extracted fields the wire
never sends, so it could only ever have rendered nothing.

The other four behaviors survive intact, and they are what removed the
clicks: thinking renders as prose in its own timeline row, the current
turn shows every work row, the latest turn's fold starts open, and the
toggle set records a deviation from each fold's default.
…g it away

The fold toggle set now records a *deviation* from each fold's default, and
the latest turn defaults to open. The interrupt handler predates that: it
adds the just-stopped turn to the set to "keep it expanded", which under the
new meaning flips the latest turn's default and collapses the very work the
comment says it is preserving.

An interrupted turn is still the latest turn, so its fold already defaults to
open — the branch has nothing left to do, on either surface. Removed from
both the web timeline and the mobile feed. The rollover branch stays: a
deviation the reader set belongs to that turn alone, and clearing it when the
next turn starts is what lets the old turn fold at its own default.

The interrupted-latest-turn test now also pins the collapse direction, so
re-adding the turn to the set reads as the regression it is.
@github-actions github-actions Bot added size:L and removed size:XL labels Aug 19, 2026
@leonardoxr
leonardoxr merged commit b48ad2e into main-xavier Aug 19, 2026
5 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant