@@ -210,10 +210,11 @@ export function itemRows(
210210 const indent = opts . indent ?? 0
211211 // Nested lines are marked by their INDENT, so each keeps the glyph that says
212212 // what it is: ● the call, ⎿ the result that came back. Only a collapsed fold
213- // ("Ran 2 tool calls") takes the branch glyph — as a notice it would
214- // otherwise wear ✦, the mark for the infrastructure speaking, which is not
215- // what a fold is.
216- const gutter = opts . nested && item . kind === 'notice' ? BRANCH_GLYPH : gutterFor ( item )
213+ // (key grp:*, "Ran 2 tool calls") takes the branch glyph — as a notice it
214+ // would otherwise wear ✦, the mark for the infrastructure speaking, which is
215+ // not what a fold is. Keyed on the fold itself, not on `nested`: a
216+ // turn-opening run is flat, and it is still a fold.
217+ const gutter = item . key . startsWith ( 'grp:' ) ? BRANCH_GLYPH : gutterFor ( item )
217218 const textPad = gutter === BRANCH_GLYPH ? BRANCH_TEXT_PAD : 0
218219 const width = contentWidth ( cols , { indent, textPad } )
219220 const shown = withRenderedMarkdown ( item , width )
@@ -270,14 +271,18 @@ export function itemRows(
270271// glyph, attached with no blank row between. Prose, user messages and notices
271272// keep their own gutter mark and their spacing.
272273//
273- // The parent is always an ASSISTANT message. A run with none before it (the
274- // agent opened its turn with a tool call) stays FLAT rather than hanging off
275- // the user message that prompted it: your message is a lifted box, and a ⎿
276- // branch under it would read as work YOU did.
274+ // INDENT and OWNERSHIP are decided separately, because they answer different
275+ // questions. A run belongs to (is opened by, travels with) whatever message
276+ // came last, YOURS INCLUDED — the agent often opens a turn with a tool call,
277+ // and a run that belonged to nothing could not be reached with →. But it only
278+ // INDENTS under assistant prose: your message is a lifted box, and a ⎿ branch
279+ // under it would read as work YOU did, so a turn-opening run stays flat and
280+ // separated by its own blank row. Only a run at the very top of the transcript,
281+ // with no message above it at all, belongs to nothing.
277282//
278- // Nesting also decides what ↑/↓ can LAND on, because a tool call is not a stop
279- // of its own — it belongs to the message that made it. Three levels, each
280- // opened by → on the level above:
283+ // Ownership is what ↑/↓ can LAND on, because a tool call is not a stop of its
284+ // own — it belongs to the message that made it. Three levels, each opened by →
285+ // on the level above:
281286//
282287// ● the message a stop; ↑/↓ walk these
283288// ⎿ Ran 3 tool calls part of the message's block (navKey → the message)
@@ -309,19 +314,23 @@ export function layOutItems(
309314 opts : { openedKeys ?: ReadonlySet < string > ; revealAll ?: boolean } = { } ,
310315) : PlacedItem [ ] {
311316 const out : PlacedItem [ ] = [ ]
312- // The ASSISTANT message the current run hangs off — null until the agent has
313- // said something, where a run has nothing to hang off and stays flat .
317+ // The message the current run BELONGS to — what → opens and ↑/↓ land on.
318+ // Either sender's; null only at the head of the transcript .
314319 let parent : string | null = null
320+ // Whether that message was the agent's, which is what decides the visual
321+ // nesting: only the agent's prose gets a ⎿ branch under it.
322+ let parentIsAgent = false
315323 // The call a ⎿ result belongs to, so a result travels with its own call.
316324 let call : string | null = null
317325 for ( const item of items ) {
318326 if ( ! isToolActivity ( item ) ) {
319327 out . push ( { item, indent : 0 , nested : false , attach : false } )
320- parent = item . kind === 'assistant' ? item . key : null
328+ parent = item . key
329+ parentIsAgent = item . kind === 'assistant'
321330 call = null
322331 continue
323332 }
324- const nested = parent !== null
333+ const nested = parent !== null && parentIsAgent
325334 const revealed =
326335 opts . revealAll === true || ( parent !== null && opts . openedKeys ?. has ( parent ) === true )
327336 if ( item . kind === 'tool' ) call = item . key
0 commit comments