Skip to content

fix(tui): preserve code rows in settled scrollback - #1143

Merged
XuPeng-SH merged 6 commits into
matrixorigin:mainfrom
loveRhythm1990:lr90/tui-copyable-assistant-scrollback
Oct 26, 2026
Merged

XuPeng-SH merged 6 commits into
matrixorigin:mainfrom
loveRhythm1990:lr90/tui-copyable-assistant-scrollback

Conversation

@loveRhythm1990

@loveRhythm1990 loveRhythm1990 commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Capability assessment: N/A: CLI/TUI scrollback presentation only; no capability, runtime-profile, or server API contract changes.

Summary

Copying a settled assistant reply could include written gutter glyphs. Removing the glyphs alone still left a second problem: the final terminal writer inserted hard line breaks inside long code lines, changing quoted commands and heredoc content at narrow widths.

Settled prose now uses plain-space indentation. Code rows start at column zero and retain their existing Markdown row classification through lazy history preparation, budget deferral, trust-boundary pushback, shutdown draining, and the final writer. Code uses terminal soft wrapping instead of application-inserted hard breaks. The writer accounts for physical rows at the current terminal width, including wide characters, combining text, and default tab stops. Zellij writes content before reserving the composer, so multi-page code remains intact after repaint and subsequent replies. A full-height input area uses the same flow to retain output in native scrollback.

Related issue

Closes #1142

Change type

  • Bug fix
  • Test
  • Documentation

User and compatibility impact

  • Settled replies no longer add a glyph marker to copied prose or code.
  • Astra adds no width-generated hard line breaks within sanitized code rows. Native clipboard behavior remains terminal/multiplexer dependent; tabs, Unicode width policy, and Markdown newline normalization are not a portable byte-for-byte clipboard guarantee.
  • The live streaming gutter is unchanged.
  • No configuration, persisted transcript format, database, or server API changes.

Architecture and complexity delta

  • Extend the existing MarkdownRow representation through the existing assistant/history/writer pipeline; no parallel renderer or additional row-policy state.
  • Keep terminal sanitization and structured-link trust independent of code layout. Both terminal modes retain the same final styled writer, cursor restoration, flush, and history bookkeeping. The writer reports whether the existing draw loop must repaint the viewport.
  • Preserve lazy layout, bounded row/byte batches, FIFO order, and progress for one oversized line. Interactive and shutdown draining share one flush implementation.
  • Remove the unused take_history_batch implementation and its implementation-only tests; replacement tests exercise the production queue and actual writer bytes.

Verification

  • Executed REDs: the old final writer inserts CRLFs inside a quoted command at 40 columns; old Zellij placement overwrites seeded history; multi-page Zellij output puts its tail in the composer. Regressions now check both writer content and placement after repaint and a following reply.
  • cargo test --locked -p astra-cli --lib tui:: -- --test-threads=1: 2027 passed, 1 pre-existing ignored.
  • cargo clippy --locked -p astra-cli --all-targets -- -D warnings: passed.
  • cargo fmt --all -- --check: passed.
  • cargo audit --no-fetch --db <fresh task-owned RustSec DB>: passed under repository policy; four existing allowed warnings. Rust dependencies and audit policy are unchanged by this PR.
  • Incremental ThreadSanitizer: 530 passed, 1 pre-existing ignored, covering existing and new tests in changed owners and directly affected consumers. Built with nightly-2026-10-12, instrumented standard library, no TSan reports or suppressions.
  • An earlier candidate (35befbe2) broader TUI TSan run passed its 2024 assertions but exited 66 with two Tokio I/O reports. Both reproduce in the unchanged browser-login fixture in isolation, outside the copy pipeline; the same function pair is reported upstream. This broader run is retained as a limitation, not described as race-clean; no suppressions were used.
  • Tests exercise the actual pending queue and final terminal writer, plus VT100 replay: 40/80/120 columns, Standard/Zellij modes, plain/highlighted code, long quoted commands, heredocs, indentation/blank lines, current-width geometry after resize, exact margins, wide/combining characters, TAB boundaries, batch budgets, an oversized line, trust-boundary pushback, control sanitization, and write failures. Added coverage includes exact-margin/multi-page rows, previously painted composer text, following replies, and full-height/empty viewports. VT100 does not retain partial-region scrollback, so Standard controls assert visible placement/repaint while full-screen flow asserts the complete scrollback content. Native clipboard testing was not performed.
  • Previous-head (2da7484a6) live-model CI: 17/18 passed; agent_workspace_evidence_chain failed its final text_contains("2024") assertion despite passing tool/event assertions. That failure remains unclassified and is not claimed fixed by this presentation-only change. Fresh CI is pending.
  • Database/live-model verification: not applicable to this presentation-only change.

Final checklist

  • Tests cover the owning behavior and unhappy paths.
  • TUI architecture documentation describes the updated contract and limits.
  • The diff contains no credentials, private endpoints, or generated runtime data.
  • Title follows the Conventional Commit format.

@XuPeng-SH XuPeng-SH left a comment

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.

Reviewed commit 3de039e89fedff6d3ac8cc056011caed08a81e8f. One P2 completeness finding is attached inline: code-row metadata is discarded before the final terminal writer, which can still insert hard newlines into copied code. The owner consolidation and removal of duplicate prefix logic are reasonable. Existing hard wrapping is explicitly distinguished from a regression introduced here. Current CI passed; the local evidence is an isolated renderer/writer probe, not a full CLI rerun or native clipboard test.

loveRhythm1990 and others added 5 commits October 27, 2026 00:05
Settled assistant replies prefixed every scrollback row with a literal
`█ ` gutter. Terminal selection copies written cells, so commands copied
from a reply came out as `█ git status` and did not run when pasted.

Mark only the first body row with `● ` (same `theme.success` colour) and
indent continuation rows with two plain spaces, matching the first-row
marker convention used by tool cells. Layout width and colours are
unchanged; the live `LiveFramedCell` gutter is out of scope.

Refs matrixorigin#1142

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The two-space continuation prefix still leaked into copied code: a
heredoc terminator became `  EOF` and no longer closed the heredoc, and
indentation-sensitive code gained an extra indent.

The Markdown renderer now marks code-block rows as verbatim, and settled
assistant replies write those rows at column 0 without any prefix, so a
selected block matches its source exactly. Prose rows keep the `● `
first-row marker and two-space indent. Tests compare the whole copied
block instead of trimmed rows.

Refs matrixorigin#1142

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A reply that is a single command still rendered as `● git status`, so
copying that row included the marker. Settled prose rows now carry only
a two-space indent and no glyph; code-block rows stay verbatim. Reply
boundaries remain visible through the surrounding user, tool, and turn
summary rows.

Closes matrixorigin#1142

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@XuPeng-SH
XuPeng-SH force-pushed the lr90/tui-copyable-assistant-scrollback branch from 3de039e to 2da7484 Compare October 26, 2026 16:39
@XuPeng-SH XuPeng-SH changed the title fix(tui): keep copied assistant scrollback free of gutter glyphs fix(tui): preserve code rows in settled scrollback Oct 26, 2026

@XuPeng-SH XuPeng-SH left a comment

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.

Approve. Deep-reviewed all 6 commits (5675499..ded8061) vs main: no Critical/Important findings. cargo test -p astra-cli --lib -- tui:: 2027 passed, 0 failed; git diff --check clean. Multi-page scrollback preservation, verbatim code rows, and Zellij/full-height flow-then-reserve paths are covered by vt100-emulation tests.

@mergify mergify Bot added the queued label Oct 26, 2026
@XuPeng-SH
XuPeng-SH merged commit 203aed8 into matrixorigin:main Oct 26, 2026
41 of 42 checks passed
@mergify

mergify Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • ✅ Entered queue — 2026-10-26 18:34 UTC · Rule: main · triggered by rule Automatic queue on approval for main
  • 🚫 Left the queue — 2026-10-26 18:35 UTC · at ded8061f7b2f946137cec0b806085d5f64f3f50e

This pull request spent 1 minute 11 seconds in the queue, with no time running CI.

Reason

Pull request #1143 has been dequeued

Pull request from fork cannot be queued. This pull request comes from a fork, and Mergify needs the author's permission to update its branch.

The author needs to enable "Allow edits from maintainers" on this pull request.

Hint

You should look at the reason for the failure and decide if the pull request needs to be fixed or if you want to requeue it.
If you do update this pull request, it will automatically be requeued once the queue conditions match again.
If you think this was a flaky issue instead, you can requeue the pull request, without updating it, by posting a @mergifyio queue comment.

Tick the box to put this pull request back in the merge queue (same as @mergifyio queue).

  • Requeue this pull request

@mergify mergify Bot added dequeued and removed queued labels Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: TUI assistant reply gutter (█ ) is copied with selected text, breaking copied commands

2 participants