feat(chat): the timeline shows the work instead of hiding it behind three clicks - #13
Merged
Merged
Conversation
…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.
…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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 = 1condensed every work group to its last row, including while the turn was still running.deriveTurnFoldshid the whole turn behindWorked for Xsthe instant it settled.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.
Show thinkingdisclosure. Tool grouping breaks around it.The default-open rule deliberately does not apply in the window between sending a message and the server creating its turn:
latestTurnstill 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:
After — thinking as clamped prose, read output inline, colored diff inline, every tool row of the current turn present:
Another thread — two thinking blocks reading as prose, intent-titled tool rows, subagent CTA, all with zero clicks:
Verification
threadActivitytests 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.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
Toolbecause 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.