- Implement `handleWheelAt` to restrict wheel scrolling to the settings pane.
- Update selection movement to support clamping when scrolling at boundaries.
- Add tests to verify boundary behavior and spatial constraints.
- Fixed streaming output being lost from native scrollback when an unstable "barrier" block preceded it.
- Adjusted the engine commit logic to ensure all scrolled-off content reaches history, treating the `windowTop` as the persistent commit floor.
- Updated the committed-prefix logic to perform range-aware auditing, ensuring forced-overflow rows are accurately re-anchored rather than dropped upon barrier finalization.
- Refactored committed prefix auditing into distinct byte-stable, durable, and forced-overflow zones.
- Integrated a hard scan detector and refined boundary management to prevent data loss during commit-unstable barrier shifts.
- Implemented robust regression testing via the streaming-scrollback-defer harness to verify frame continuity.
- Updated audit logic to independently manage boundaries, ensuring forced-overflow rows remain correctly finalized.
Shows live per-command status (plan/goal/loop/model/advisor/collab/jobs/
context/...) in the slash-command autocomplete.
Adjustments on merge:
- Exclude the two .github/pr-assets/*.png screenshots.
- Resolve the autocomplete.ts conflict keeping main's skill-command empty-prefix
boost alongside the new static-vs-display description split.
- Compute the live display description lazily — only once a command actually
matches (name or alias) — instead of for every command on each keystroke, and
guard the getter with a typeof check. getAutocompleteDescription reads live
session state, so the eager call was O(commands) work per refresh.
- Stripped `<span>` and `<text>` tags from rendered markdown while preserving their contents.
- Updated HTML entity normalization to handle common special characters and numeric codes within the TUI.
- Ensured whitespace surrounding stripped inline tags is preserved, preventing content merging.
Preserved the leading whitespace in the suggestion prefix and routed both Enter paths in editor.ts through findLeadingSlashCommandStart so the popup apply and sync fallback no longer bail out on ' /sk'.
Fixes#3095
Handled slash commands when / is the first non-whitespace token so suggestions, inline hints, and synchronous Enter completion all share the same trigger.
Fixes#3095
Handled leading whitespace before slash command autocomplete, inline hints, and synchronous Enter completion.
Added regression coverage for indented slash command suggestions, argument hints, Tab acceptance, and sync submission.
Fixes#2875
- Replaced usage of `ReturnType<typeof setTimeout>` and `ReturnType<typeof setInterval>` with the explicit `Timer` type across the codebase.
- Updated several type definitions and function signatures to use concrete types instead of inferred return types for improved clarity and maintainability.
- Added `BoxBorder` interface and optional border support to the `Box` component.
- Implemented `setBorder()` to allow dynamic toggling of box outlines.
- Added intelligent border dropping logic to prevent overflows in narrow containers.
- Added comprehensive unit tests for rendering, styling, and boundary conditions.
- Implemented `customHr` tokenizer to support varied Unicode horizontal rule characters.
- Added logic to intelligently map divider characters to theme-appropriate symbols.
- Updated theme object ID tracking to use `WeakMap` for better handle integrity.
- Removed configurable tab width support and the `display.tabWidth` setting across all packages.
- Deleted obsolete utility functions `getIndentation`, `getIndentationNoescape`, and `setDefaultTabWidth`.
- Standardized tab expansion logic to use a fixed `DEFAULT_TAB_WIDTH` globally.
- Cleaned up related configuration schemas, test suites, and internal API signatures to remove path-dependency.
- Standardized elision markers across all tool outputs and filters to use cohesive `[...N [type] elided...]`, `[...Nln elided...]`, and `[...xB elided...]` syntax.
- Updated documentation, prompts, and test expectations to reflect the unified elision format.
- Improved transcript viewer robustness by preventing content aliasing through path-inclusive signature hashing.
- Added logic to clear stale transcript content when associated session files are deleted, accompanied by verifying test cases.
- Prevent interleaved ordinary renders from forcing a full redraw during active viewport resizing.
- Remove redundant state tracking in favor of a direct check against forced-render flags, ensuring live updates like spinners remain within the optimized drag path.
- Add regression test to verify that mid-drag renders do not trigger unintended transcript repaints or alternate screen exits.
Pretty-printed HTML lists (e.g. <ul>\n <li>...) leaked source
indentation before bullets and inserted blank rows between items
because whitespace-only text between block-level tags was appended
literally. Skip insignificant formatting whitespace and pin it with
a regression test.
- Centralized decoding of tmux's `extended-keys` control sequences (`csi-u` and `xterm` formats) into a shared utility.
- Updated the multi-line editor and single-line input to use this decoder, preventing escape tails (e.g., `[27;5;106~`) from leaking into the text buffer.
- Added parity to the single-line input by explicitly stripping any remaining control characters after decoding to ensure data integrity.
Bottom-anchored overlays now crop from the top when terminal-height clamping applies, keeping footer action rows visible in plan review.\n\nFixes #2957
- Added new `tui.tight` setting with default `false` and documented behavior.
- Added global tight-mode APIs and `setIgnoreTight` propagation across Box, Text, and Markdown.
- Handled `tui.tight` updates to refresh UI borders and trigger rerendering.
- Updated key message components to ignore tight mode selectively and preserve intended spacing.
- Adjusted image budget IDs to use a shared 24-bit seed and wrap safely so new budgets no longer collide.
- Added transmit-state reset and changed image output ordering so full paints can replay image data after terminal clears.
- Updated image and protocol tests to match the new wrapped-id behavior and cursor-save/restore-wrapped transmit sequences.
Prioritized /skill:* entries for the empty slash autocomplete query so user skills appear in the initial popup instead of below all built-ins.
Added autocomplete regression coverage for empty slash query ordering.
Fixes#2875
- Added cursor save/restore escape handling around direct image emission.
- Replaced the previous up-and-down cursor movement sequence with restore logic to keep renderer output positioned correctly.
- Ensured direct image replay path no longer depends on moving back down after placement to align the cursor.
- Added Matplotlib figure PNG rendering and display tracking in Python runner to emit PNG output immediately when figures are displayed via display(fig).
- Extended session persistence to externalize oversized image payloads in both content and details.images, enabling tool result images to survive session reload.
- Enhanced session loader to resolve image data payloads and blob references across content and details.images during session reconstruction.
- Added image cache invalidation in TUI image component when image protocol, cell dimensions, or Kitty Unicode placeholder mode changes.
- Added comprehensive test coverage for Matplotlib display, image persistence across reload, and TUI image rendering with protocol and dimension changes.
Added C=1 to Kitty display commands so direct inline-image cursor restoration is the sole row accounting path. Updated focused image rendering and placement encoding coverage.\n\nFixes #2863
Restored the cursor below direct inline-image placements after emitting the graphics sequence so following chat rows cannot overwrite the reserved image area. Added coverage for the placement row terminator.\n\nFixes #2863
A semicolon-form extended color with a missing component (e.g. 38;2;255;0
lacking blue, or 38;5 lacking the palette index) has ambiguous arity: if
a following SGR is concatenated onto it, the next code is absorbed as the
missing channel/index and the rendered color changes. Stop a merge run at
any parameter list that ends mid extended-color so the following sequence
keeps its original framing. Complete colors and the self-delimiting colon
form still merge, so the win is unchanged on real transcripts (34.3% SGR
reduction on the sampled capture). Adds regression tests for incomplete
truecolor/indexed runs and the complete-color merge.
The renderer's component tree emits each styled span as
<set-color>text<reset>, producing runs of byte-adjacent SGR sequences.
Two byte-adjacent SGR sequences are semantically identical to one SGR
carrying both parameter lists (params apply left-to-right), so merging a
run into a single CSI is behavior-preserving and cuts per-frame byte
volume and SGR-dispatch count on slow terminal engines (xterm.js/WebGL
under a large viewport). Each emitted sequence is capped at 16 parameter
tokens so long runs split across several valid CSIs instead of
overflowing a terminal's parameter buffer. On by default; disable with
PI_NO_SGR_COALESCE=1.
- `ProcessTerminal` now captures a per-instance `#headless` from `isTerminalHeadless()` at construction and re-reads it in `start()`; when set, `#safeWrite`, `start`, `stop`, `drainInput`, and `setProgress` short-circuit, so frame paints, `start()` probes (OSC 11 / DA1 / kitty), the progress keepalive, stdin raw mode, SIGWINCH, and teardown escapes no longer reach a real terminal during `bun test` (previously `#safeWrite` only skipped on `!isTTY`, so an interactive terminal leaked stray boxes and probe queries).
- Gated the `emergencyTerminalRestore()` blind-restore branch and `TerminalInfo.sendNotification` on the headless flag, and guarded `setTerminalTitle`/`pushTerminalTitle`/`popTerminalTitle` in `title-generator.ts`.
- Opted the terminal-contract suites (terminal-appearance, notifications, emergency-restore-altscreen, issue-2034 write gate, process-terminal-render-harness, render-stress-harness) back into real I/O with `setTerminalHeadless(false)`, restoring on teardown.
- Added `process-terminal-headless.test.ts` asserting zero writes under a forced TTY when headless and real frame/probe output after opt-out.
- Added latexToBlock module that renders stacked fraction math with baseline-aware rows.
- Updated markdown rendering to route display math through latexToBlock with sole-display handling.
- Exported latexToBlock from the package entrypoint and updated changelog docs accordingly.
- Added advisor resume and suppression repro tests in coding-agent for interrupted turn recovery.
- Added own-line display-math tokenizers for `$$...$$` and `\[...]` markdown blocks.
- Added delimiter-free `\begin...\end` math parsing in text conversion with multiline row preservation.
- Added ANSI rendering for `\textcolor`, `\color`, `\colorbox`, and `\fcolorbox` with scoped color resets.
- Added tests for LaTeX color and math parsing edge cases, including inline code and nested scopes.
- Added LaTeX math and Mermaid allowances in terminal and final-chat prompts.
- Added inline math tokenization in TUI for $, $$, \(\), and \[\].
- Added LaTeX-to-Unicode conversion helpers and exports for math rendering.
- Fixed inline math detection to skip escaped dollars and currency-like spans.
- Removed render_mermaid from tool discovery, task definitions, and registries.
- Removed renderMermaid setting and prompt/docs references tied to the deleted tool.
- Added maxWidth and theme color options to Mermaid ASCII resolution in markdown flow.
- Re-rendered Mermaid ASCII in both directions and clipped output to available width.
Overlay roots can now declare nested focus targets they own so visible overlays keep their active child focused while background prompt focus steals remain blocked.
Updated the setup wizard to register scene prompt focus targets and covered the nested prompt path in the overlay focus regression test.
Fixes#2789
Background approval prompts could steal TUI focus from visible overlays such as /settings, leaving keystrokes routed to a hidden surface.
Pinned the focused component to the top visible overlay and added a regression test for the always-ask approval focus path.
Fixes#2789
Break the Warp resize feedback-loop redraw storm by env-pinning resize classification. Merge resolves the issue-2088 test against #2755 by keeping the CMUX env-clearing setup and adding #2741's TERM_PROGRAM/PI_TUI_RESIZE_IN_PLACE neutralizers.
Detect CMUX as a multiplexer via CMUX_WORKSPACE_ID/CMUX_SURFACE_ID. NOTE (owner-accepted caveat): introduces a test-isolation gap - direct-terminal TUI tests fail when the suite is run inside a cmux terminal (CI unaffected); follow-up to consolidate multiplexer-env clearing into a shared helper.
Disable xterm modes 1010/1011 so terminal output and keypresses no longer force scroll-to-bottom while editing; restore the originally-set modes on stop().
The printable-first short-circuit in matchesKey/parseKey decoded every printable CSI-u/modifyOtherKeys sequence, so canonical named keys carrying a printable codepoint (space=32, shifted letters, DEL=127) stopped normalizing through the native matcher: parseKey returned a literal space instead of "space" and DEL instead of "backspace", breaking keybindings and deletion.
Restrict the fast path to the keypad numpad/operator codepoints the native protocol misclassifies without a NumLock modifier (decodeKittyKeypadText); everything else falls through to native normalization. Also filter DEL out of the modifyOtherKeys decode so it is never inserted as text, and reuse KITTY_MOD_NUM_LOCK in the lock mask (its original gate was removed, leaving it unused and failing lint).
Addresses review feedback on #2767.
Throttled animated loader message-only repaints when synchronized output is unavailable so unsupported terminals only repaint on spinner frame changes.
Fixes#2771