- Fixed assistant transcript blocks to expose append-only commit-safe boundaries.
- Updated TUI live-region commit and pinned-paint logic to clamp commit-safe ends.
- Fixed long streamed assistant replies to remain in native scrollback on overflow.
- Treated terminal resize as explicit reconcile to erase mis-wrapped scrollback.
- Prevented viewport-repaint capping from leaving corrupt history on screen.
- Replaced conditional viewport-repaint/history-rebuild branches with an unconditional reset on any geometry change.
- Multiplexer panes still repaint in place since pane scrollback cannot be erased.
- Dropped no-overflow and confirmed-scrolled guards: scrolled readers snap to bottom and shell scrollback is cleared.
- Updated and removed tests reflecting the new reset behavior.
- Prevented foreground streams from committing live rows, which left a stale pending tool box above the running box.
- Added initial live-region pinned paint for ED3-risk hosts with unknown viewport.
- Reconciled stale cached DEC 2048 geometry against live OS dims on resize so content reflows.
- Disabled eager native-scrollback rebuild at once when no render is pending, so later content mutations don't inherit foreground-stream privileges.
- Deferred ED3-risk unknown-viewport shrinks completely instead of padded-repainting over scrolled history.
- Skipped suffix-suppression and offscreen-mutation branches on resize so geometry reflow repaints at the new size.
- Routed overlay visibility reductions through the explicit reconcile path so they bypass streaming deferral and rebuild once.
- Skipped the deferral when the terminal reports its viewport is at the tail, preventing dropped rows above the viewport top.
- Separated commit geometry from repaint geometry in the pinned repaint.
- Clamped repaint to the committed sealed boundary so a mid-turn collapse no longer re-exposes already-committed rows.
- Deferred stale mutable live-region lines to the next checkpoint.
- Removed clamp to sealed-prefix boundary so off-screen rows above the viewport top enter native scrollback.
- Prevents erasing the head of a tall live block (long stream, big tool result) that alone overflows the viewport.
- Added `NativeScrollbackLiveRegion` seam so components report the live suffix start.
- Stopped ED3-risk streaming from dropping sealed transcript rows above the live block.
- Appended newly sealed rows once while keeping the active tail deferred to checkpoint.
- Threaded a geometry-changed flag into the pinned emitter.
- Deferred width/height changes to the reflow rebuild path, since relative cursor moves from pre-resize geometry landed on wrong rows.
- Replaced full-screen clear (ED2) and absolute home with relative cursor moves and per-line `\x1b[2K`.
- Threaded prior viewport top and hardware cursor row to compute the relative move.
- Stopped Ghostty from snapping a scrolled-back reader to the bottom on every live-tail frame.
- Added NativeScrollbackLiveRegion seam reporting where a component's transient suffix begins.
- Pinned the live block and chrome below it out of native history during foreground streams on ED3-risk terminals.
- Consumed pending forced scrollback wipes while pinned to avoid yanking a scrolled-up reader (#1682).
The 15.9 placeholder rollout enabled the U=1/U+10EEEE grid by default for
every terminal advertising the Kitty image protocol. Only kitty and
ghostty actually ship a working implementation; WezTerm advertises Kitty
graphics but has not implemented placeholder support (upstream
wezterm/wezterm#986 has it unchecked), and the tmux/screen fallback can
force Kitty mode on any outer terminal (Terminal.app, etc.).
On those paths every placeholder cell rendered as a literal PUA box
glyph - the screenshot in #1877 - and each repaint re-emitted the full
columns x rows grid (~4.8KB per frame for a typical 80x20 image vs ~22
bytes for the direct a=p APC), which produced the laggy scrolling.
Add detectKittyUnicodePlaceholdersSupport(terminalId, env) and seed the
feature flag from terminal-capabilities after TERMINAL_ID resolves.
Defaults on only for kitty and ghostty; everything else falls back to
direct a=p,i=...,p=... placement, which those paths already render
correctly. PI_NO_KITTY_PLACEHOLDERS=1 remains a hard opt-out, and a new
PI_KITTY_PLACEHOLDERS=1 opts in on otherwise-unsupported terminals (for
e.g. wezterm nightlies that have merged placeholder support).
Fixes#1877
- Updated the TUI commit-path guard so unstable overflow falls back to normal commits unless rewrites reach above the viewport top.
- Added a regression test that streams a growing box while scrollback risk is enabled and checks all logical rows stay reachable in history or view.
- Adjusted session and dashboard renderers to derive heights from live terminal rows.
- Propagated terminal-row callbacks through picker/controller wiring and session selectors.
- Reworked list visibility and page navigation to honor row-based budgets and footer lines.
- Added DECRQM 2031 startup probing and stopped OSC11 polling once support was confirmed.
- Added assistant-message completion state and stable-line count reporting.
- Added transcript stable-row aggregation and snapshot replay to keep unstable rows out of scrollback.
- Added TUI stable scrollback boundary APIs and stable-prefix commit path.
- Added regression tests proving unstable rows stay out of scrollback until stabilized.
- Added cursor remapping support to deferredMutation intents and emitted cursor positions when deferring offscreen mutations.
- Introduced planDeferredShrink to defer bottom-anchored offscreen deletions only when displayed rows were byte-identical, otherwise repainted the viewport.
- Added regression tests covering unknown-win32 offscreen middle-shrink behavior, including cursor-only moves and tail-content-change cases.
- Added TranscriptContainer that snapshots non-live blocks to avoid stale scrollback duplicates.
- Thawed snapshots at prompt-submit checkpoints for reconciliation.
- Repainted eager streaming tail on overflowing shrink to unfreeze UI (issue #1682).
- Removed deferredMutation no-op that drifted the live tail upward.
- Repaint emits no ED3 and keeps tail-followers off stale tool previews.
- Preserved scrollback cleanup via nativeScrollbackDirty checkpoint.
- Renamed `TodoWriteTool` to `TodoTool` and its source/prompt files.
- Updated tool registration, schema, renderers, and gating to `todo`.
- Adjusted cursor provider native tool names and tests to match.
- Renamed strike-animation constants and `todo-error-reminder` type.
- Moved hardware cursor up to the real content bottom instead of the padded viewport bottom.
- Prevented terminal height shrinks from scrolling live rows into scrollback and duplicating them per resize step.
- Kept relative rowDelta math correct so IME cursor still lands right after height-grow resizes.
- Added `textSizing` terminal capability and `tui.textSizing` setting for Kitty OSC66 scaling.
- Updated OSC66 range and visible-width handling to preserve grapheme slice behavior.
- Updated markdown rendering to apply heading text sizing only when enabled.
- Fixed DECCARA trailing-background fill tracking and DECRPM status 3/4 recognition.
- Enabled OSC99 probe parsing and title advertisement checks before using rich output.
- Enabled Kitty probe negotiation on startup and switched transmission to temp-file on OK replies.
- Enabled direct-mode fallback when Kitty probes return non-OK or unsupported responses.
- Added non-destructive viewport clear behavior to emit CSI22J then 2J+H without 3J.
- Preserved destructive clear path to keep sending 2J+H+3J when clearScrollback is enabled.
- Adjusted DECCARA fill offsets and fallback rendering to preserve row fills after scrolling overflow.
- Added terminal write capture helpers and DECCARA parity tests, including deterministic fuzz checks.
- Added kitty-graphics module with Unicode placeholder and temp-file APIs.
- Refined terminal image handling to use rendered placeholder lines and detect placeholder output.
- Raised the max inline-image default from 3 to 8 in schema and image constants.
- Refined terminal capability flow for Kitty support, including screen-to-scrollback and text-sizing handling.
- Added integration tests for kitty placeholders, virtual placement, and temp-file rendering.
- Added OSC 66 text-sizing utilities and `encodeTextSized` for safe, width-aware span emission.
- Enabled scale-2 OSC 66 output for H1 headings when text sizing is enabled and width permits.
- Handled OSC 66 heading rows as raw output, skipping wrap/background and preserving the reserved blank row.
- Mapped inline heading tokens to plain text to gate OSC 66 heading rendering by measured width.
- Added `ImageBudget` keeping only N recent images live, demoting older ones to text via a full redraw plus Kitty graphics purge.
- Changed Kitty images to transmit-once + placement, so repaints re-send only tiny placement sequences instead of base64.
- Added `tui.maxInlineImages` setting (default 3, 0 disables) wired through the coding-agent renderers.
- Added render scheduling interfaces and optional TUI options for injectable timing.
- Replaced direct timeout/scheduling calls with scheduler-based render timing and timestamps.
- Updated stress harness logic to use deterministic scheduler and column-based expected backgrounds for rendering checks.
- Tightened positive-integer parsing in render-stress tests to throw on malformed or non-positive values.
- Expanded render-stress oracle coverage for scrollback, probe caps, and frame/overlay helpers.
- Marked native scrollback dirty on resize when overflowing content was not at bottom, to resync history at checkpoint.
- Added reflow-based line wrapping and verify scenarios in stress harness to exercise resize-count changes.
- Adjusted checkpoint/reconciliation assertions to model foreground-streaming scrollback deferral and cleanup.
- Repainted bottom-anchored tail during eager rebuild instead of pinning the pre-shrink top.
- Re-anchored viewport when a shrink moves the window above the lagging high-water mark.
- Added ghostty fuzz test for chip injection over active tool renders.
- Added `PI_NO_SYNC_OUTPUT=1` env var to disable DEC 2026 wrappers while keeping autowrap guards active around paints.
- Removed Termux-specific height-change no-op; all non-multiplexer resizes now repaint to prevent phantom blank rows.
- Added `linux-normal-vteNoSync-small` stress scenario and issue-1765 regression tests.
- Deleted `shouldTrustNativeViewportProbe` and `ProcessTerminal.isNativeViewportAtBottom` — ConPTY pins the pseudo-console buffer to the visible grid so the probe always lied "at bottom," yanking scrolled readers in Tabby, Hyper, VS Code, and conhost (#1746).
- Every Windows host now treated as viewport-unobservable; live mutations defer destructive rebuilds and reconcile at prompt-submit checkpoints.
- Added `issue-1746-repro.test.ts` and `win32-unknown-small` stress scenario to lock the anti-yank contract end-to-end.
- Fixed phantom blank rows spliced into scrollback when resize events net unchanged dimensions, coalesce with appends, or land in multiplexer panes.
- Fixed tmux pane history duplicating on dirty-scrollback live frames, forced renders, and checkpoint replays; destructive rebuilds now blocked inside multiplexers.
- Fixed WSL+Windows Terminal classified as ED3-risk so eager streaming rebuilds defer instead of yanking scrolled readers.
- Fixed turn-end teardown freezing on ED3-risk terminals by deferring eager-mode disable until after frame classification.
- Guarded eagerEraseScrollbackRisk with a win32 platform exclusion to avoid incorrect deferred mutations on Windows.
- Added early deferredMutation exit for unobservable ED3-risk shrinks outside foreground-tool streaming.
- Fixed viewport drift on direct-input shrinks by returning viewportRepaint when naturalViewportTop shifts.
- Removed unused #nativeViewportIsAtBottom helper.
- Replaced deferred-mutation early exit with viewportRepaint for unobservable ED3-risk shrinks that exceed the padded viewport top.
- Kept historyRebuild for ordinary POSIX terminals in the same path.
- Added regression test verifying the live UI stays visible and scrollback flushes on next checkpoint.
- Passed `allowUnknownViewportMutation: true` when requesting render after focused component handles input.
- Added regression test verifying deferred shrink repaint flushes on user keypress.
- Added early-exit path when viewport position is unknown and terminal has ED3 risk, marking scrollback dirty instead of issuing historyRebuild.
- Added regression test covering the deferred-mutation path and explicit checkpoint flush.
- Guarded existing POSIX historyRebuild tests against eagerEraseScrollbackRisk side-effects.
- Added Arabic combining/tashkeel text to stress harness to cover nonspacing-mark width measurement.