Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/changes/unreleased/1330-bare-numbered-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
kind: fixed
title: Number-only assistant replies remain visible
pr: 1330
# Optional. Which part of the repository this touches, so a reader can skip it.
# One or more of: build, chat, docs, engine, remote, resident
surface: [chat]
# Optional, and the reason this file exists. Every statement that WAS true and is
# not any more, written whole: what it was, and what it is now. A model reading
# this has to be able to check its own memory against it, so "branch names" is
# useless and "the trunk was chat-v3-task and no longer exists; work goes to dev"
# is the whole point. Leave the list empty if nothing anybody believed changed.
invalidates: []
---

The Markdown renderer now keeps an empty ordered-list marker in the transcript,
so replies such as `32.` are not silently dropped.
11 changes: 11 additions & 0 deletions internal/tui2/prose/prose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,17 @@ func TestOrderedListsShareARightEdge(t *testing.T) {
}
}

// TestABareNumberedReplyStillDraws holds the reply boundary where Markdown
// parses a number and full stop as an ordered list with an empty item.
func TestABareNumberedReplyStillDraws(t *testing.T) {
for _, src := range []string{"32.", "1024."} {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reply-shaped case isn't the only thing that was being dropped — any body-less item took its own marker down with it, anywhere in a list. On dev, "1. one\n2.\n3. three" renders as

1. one
3. three

and with this change it renders all three rows. That's the case a future refactor of the pop/pending contract is most likely to re-break, and it's silent when it does, so it's worth an assertion here alongside the two bare numbers.

rows := plain(render(t, src, Options{Width: 80}))
if got, want := strings.Join(rows, "\n"), src; got != want {
t.Errorf("Render(%q) = %q, want %q", src, got, want)
}
}
}

// TestBlockquoteCarriesItsGutter checks that the bar runs down EVERY row of the
// quote including the blank one between its paragraphs — a dashed bar reads as
// two quotes.
Expand Down
5 changes: 5 additions & 0 deletions internal/tui2/prose/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,11 @@ func (r *renderer) list(n *ast.List) {
saved := r.push(first, indent)
before := len(r.out)
r.container(c, !n.IsTight)
// A marker with no item body is still source text. Emit the pending
// prefix so a reply such as "32." cannot collapse to zero rows.
if len(r.out) == before {
r.emit(nil)
}
r.pop(saved, len(r.out) > before)
}
}
Expand Down