The multiline editor's key dispatch checked a hardcoded Ctrl/Shift+Enter
-> newline branch before the config-driven tui.input.submit branch, so a
user remap of submit onto Ctrl+Enter was swallowed as a newline and never
submitted. Gate the hardcoded newline fallbacks behind an explicit submit
binding; the bare-LF (iTerm2 Shift+Enter) case stays exempt because its
canonical form is indistinguishable from plain Enter.
Fixes#8906
TUI.render merged live-region seams with a topmost-seam-wins rule that
adopted only that seam's pin policy for the whole frame. While the primary
turn streams, the transcript reports the topmost, unpinned seam, so the
frame-wide pin flag becomes false and a pinned AnchoredLiveContainer below
it (the /btw panel, the working HUD) loses its pinning: once its content
grows past the viewport, the emit path commits the scrolled-off rows as
frozen snapshots on every growth frame, piling duplicates into native
scrollback.
Track a pinnedBoundary (start row of the topmost pinned region)
independently of which seam wins the topmost merge, and cap every commit
ceiling at it. Equivalent to the prior behavior for a fully-pinned frame
and for a frame with no pinned region; only the mixed case changes.
Fixes#8793
Retry: deflaked tui IME preedit border test (#5563) — VirtualTerminal.waitForRender's fixed 40ms sleep raced TUI's throttled render timer on starved CI runners, reading the pre-input frame; waitForRender now takes an optional settle predicate polled up to 2s and the test keys on the rendered content.
The startup graphics probe only ran on ConPTY hosts with WT_SESSION, so a
SIXEL-capable terminal that exposes no identifying environment variable
(foot exports TERM=foot and COLORTERM=truecolor only) resolved the
trueColor capability row, kept imageProtocol null, and rendered every
image as the "[Image: …]" text card.
The XTSMGRAPHICS branch also had its status inverted: per xterm ctlseqs a
reply of `CSI ? 2 ; Ps ; Pv S` carries Ps = 0 on success, and a terminal
without SIXEL reports a zero maximum geometry, so a successful reply was
read as unsupported.
Drop the dead DA1 half of the probe with it: ProcessTerminal swallows
every `CSI ? … c` reply for the whole session so a late one cannot leak
into the composer (#8542), which means the attribute list never reached
the probe's input listener on any platform. The bare `CSI c` it wrote was
also unaccounted for in the DA1 sentinel FIFO, so its reply consumed
another probe's sentinel.
PI_FORCE_IMAGE_PROTOCOL, including its off/none kill switch, still wins
over the probe.
isMultiplexerSession() treats TMUX, STY, ZELLIJ, HERDR_ENV=1, the CMUX_*
markers and a tmux/screen TERM as authoritative, and routes rendering down the
path that cannot rebuild scrollback. Nine tests across four files assert the
destructive full-paint behavior and fail for anyone running the suite inside
tmux, screen, Zellij or CMUX.
component-render.test.ts already cleared HERDR_ENV for exactly this reason but
covered only one of the nine signals. Replace it with a shared helper that
clears the whole family and restores it afterwards, and call it from the other
three files.
- Added live tracking and stale status warnings for agent activity snapshots.
- Fixed text wrapping with ANSI escape sequences to defer style open sequences after whitespace.
- Added VirtualRenderScheduler for deterministic virtual-clock rendering tests.
- Replaced Reflect.deleteProperty teardown with the descriptor-preserving restoreProperty pattern used by the other ProcessTerminal suites, so real isTTY/setRawMode/columns/rows own-properties survive on TTY hosts and later test files are not poisoned.
The private-CSI reassembly gate and the DA1 swallow were both guarded by
`#da1SentinelOwners.length > 0`, so a Device-Attributes reply that arrived
after the startup capability-probe sentinel FIFO drained fell through to the
input handler and leaked into the composer as literal text (e.g.
`1;22;...;52c`). The extra latency of an SSH/zmx PTY chain makes the race
observable.
`CSI ? ... c` and split private-CSI responses are terminal->host reports,
never keystrokes, so they are now consumed regardless of whether a sentinel
is still outstanding.
Fixes#8542
- Replaced time-based sleeps and polling loops with event-driven promise resolvers and fake timers across agent and tool tests.
- Migrated test suites to share in-memory auth storage and fixtures using lifecycle hooks.
- Updated catalog model definitions, metadata, and configurations.
The deterministic replay oracle only models in-place resize for tmux and
direct HerdR, but an inherited PI_TUI_RESIZE_IN_PLACE=1 makes the runtime
treat every scenario as in-place and desyncs the oracle. Add the key to
the stress env patch so a developer's override cannot leak into replay.
The HerdR flicker fix routed direct HerdR panes onto the in-place
multiplexer resize path, but the randomized render-stress oracle still
modeled them as ED3 replaying direct terminals. The width-epoch ledger
now applies to any in-place-resize scenario (multiplexer + direct HerdR)
via a dedicated resizeRepaintsInPlace trait, keeping HerdR's direct
scrollback semantics intact. Adds a deterministic replay regression
(seed 0xcafed00d, 24 iterations) that fails without the oracle update.
The watchdog discarded every overshoot longer than `sleepMs` (60s) as
system sleep, on the rationale that "the process could not have run JS
during the missed interval". That is true for a suspended process and
false for a CPU-bound wedge, which is exactly the case where JS ran the
whole interval at 100% CPU.
Duration cannot separate the two: both produce an arbitrarily large gap.
Keying the suppression on magnitude therefore dropped the most severe
stalls and kept only the mild ones, so the probe went quiet precisely
when it had something to report. Issue #5372 shows an 82,391ms block that
16.4.8 logged and current builds do not.
Classify by mechanism instead. `cpuNow()` reads process CPU time, and an
over-`sleepMs` gap is suppressed only when the process also burned less
than half of it on CPU. A resumed process shows a gap it did not spend
CPU on; a wedged one shows a gap it spent almost entirely on CPU. The
observed CPU time is included in the log line so a reader can tell which
kind of stall they are looking at.
Refs #5372, #7328, #6145
Direct HerdR panes no longer clear/replay via ED3 on resize; the
scenario description still claimed the old behavior. Aligns the comment
with PR #8433.
Revert the unrelated object-literal reflow bundled into the PR merge,
keeping only the direct-HerdR in-place resize routing, its tests, and
docs. PR #8433 (@roboomp).
Scoped direct Herdr multiplexer behavior to resize repaint selection so explicit transcript replacements continue to clear and replay scrollback.
Added coverage for resize stability and resetDisplay ED3 behavior.
Kept direct Herdr panes on the host-safe in-place resize path so streaming redraws no longer clear and replay pane scrollback.
Updated the resize regression, stress scenario, renderer docs, and changelog.
Fixes#8431
- Remove redundant definedness, null, and type checks across test suites in multiple packages.
- Clean up unused assertions, metadata tests, and obsolete test cases.
- Add good versus bad test filter guidelines and requirements to project documentation.
- The mux pane-growth oracle treated every physical scroll as a logical append, but immutable-history recovery can recommit a corrected suffix after an off-screen mutation without advancing the shadow tape; exempt only changed shared history prefixes.
- The frame-neutral oracle compared prepared rows only; at narrow widths distinct raw rows prepare identically, so the renderer's raw-prefix divergence recovery recommits legitimately. Snapshot raw frames and allow declared transient growth.
- OSC66 spacer preservation intentionally composes six bounded context rows above the resize viewport; assert that exact bound instead of zero above-fold rendering.
Both oracle false positives reproduce identically at the PR head that introduced the harness (4cc9725037); three full randomized stress passes green after the fix.