- The Image line's CUU(rows-1) clamps at the viewport top once the block's
leading rows scroll out, re-anchoring the full image shifted down; Kitty
replace-by-id then strips the prior placement's cells, scrollback included -
permanently cropped inline images on WezTerm/Warp.
- The renderer now rewrites placement lines at write time, clipping the source
rectangle (y=/h=) to the visible slice, and advances the placement id (epoch)
exactly when cells attached by the current epoch enter native scrollback:
every rendered frame feeds its raw commit target to the budget, crossing an
epoch's attach top latches a per-image archived flag, and the next emit
consumes it. Era-local comparisons keep ledger rewinds (duplication-never-
loss recommits) correct by construction; no-commit rewrites (overlay
show/hide) keep replacing the same id. The watch set bounds the per-frame
scan to live un-archived placements regardless of session length.
- Destructive ED3 replays restart epochs and delete every registry entry each
image placed (placement-scoped d=i, data retained) before re-placing under
epoch 1, so repeated resets cannot strand terminal-side placements.
- Verified against WezTerm 20240203 cell-attachment debug logs: straddling
frames attach exactly the visible slice, the finalize commit writes a full
archive copy under a fresh id, and resetDisplay deletes exactly the ids the
image ever placed.
- Removed the Loader backpressure cap so slow ConPTY paints retain the documented proportional duty cycle.
- Made WSL terminal-title working state static to avoid a second periodic OSC write loop.
Fixes#8012
Share display-command arity with readArg and consume exactly that many
required arguments across whitespace. This keeps continuation newlines
collapsed to spaces without separating a nested command from its own
argument or letting it absorb the outer command's next argument.
Cover adjacent, spaced, and source-line-split sqrt and nested-fraction
numerators.
Fixes#7996
Track pending command arities as nested frames instead of replacing the
outer frame when an unbraced command supplies an argument. Match readArg
by treating each command and its attached groups as one outer atom, while
retaining only that command's own missing arguments.
This keeps fractions such as `\frac\sqrt{a}\n{b}` waiting for their
denominator without folding standalone braced rows.
Fixes#7996
The first pass suppressed the top-level newline split whenever the next
row opened with `{`, folding a genuine braced row (`a\n{b+c}`) into the
row above. Gate the continuation on bracesOwed(): a newline joins to the
next row only when the current row ends with a command still awaiting a
brace argument (`\frac{num}\n{den}`, `\frac\n{a}{b}`, `x^\n{2}`); a row
that merely opens with a braced group stays a real row break.
Fixes#7996
latexToBlock pre-split display math on top-level newlines to stack a
`lhs =` line above its block, but a newline between `\frac{num}` and
`{den}` falls at brace-depth 0 and was treated as a row break, severing
the fraction from its denominator and rendering it as fragmented text.
Treat a top-level newline whose next non-space token opens a `{…}`
argument group as an argument continuation rather than a row break, and
collapse those interior newlines to a space so the argument reader parses
both brace groups.
Fixes#7996
Add the Unreleased entry for the desktop-notification fix and correct
the hasLinuxDesktopSession docstring, which still claimed the check was
limited to a session bus address in env.
Addresses review feedback on #7707.
- Implemented in-house, zero-dependency utility modules in `pi-utils` covering DOM manipulation, markdown parsing, templating, browser automation helpers, and terminal buffers.
- Migrated packages across the repository to consume the new internal utilities and `omptype` schema validators instead of external dependencies.
- Removed multiple external runtime and development dependencies including Zod, Marked, LRU cache, Turndown, and Puppeteer browser packages.
The SIXEL capability probe gated on process.platform === "win32", but
under WSL process.platform is "linux", so the probe never ran and inline
images fell back to the text placeholder even on Sixel-capable Windows
Terminal. Gate on isConPTYHosted() (native win32 or WSL) instead; the
existing WT_SESSION and TTY requirements still scope it to WT.
Fixes#6009
Table rows splice every wrapped cell line between unstyled border glyphs.
The native wrap deliberately leaves fg color and bold/italic open at line
ends so continuation lines can re-open them, so a codespan broken across a
wrap leaked its color into the '|' borders, inter-cell padding, and the
following cells. Close SGR state per cell line (bold/italic off, default
fg; background preserved) in #wrapCellText.
Closes#7575
Use isConPTYHosted() instead of process.platform === "win32" so the
flag-4 avoidance also covers WSL under a Windows terminal (where
process.platform is "linux" but stdout still crosses ConPTY).
Add CHANGELOG entry under [Unreleased] for this user-facing fix.
Remove the US-layout-specific SHIFT_MAP fallback from keys.ts (not
needed with flag 1, and wrong for non-US layouts).
Move the Windows platform check before the flag-2 preservation branch
in terminal.ts so that Windows always avoids flag 4, even when a parent
TUI has already enabled flag 2. In that case, push flag 3 (1+2) instead
of flag 7 (1+2+4).
WezTerm/ConPTY on Windows drops Shift+letter keypresses entirely when
Kitty keyboard protocol flag 4 (report alternate keys) is set. Fall
back to flag 1 (disambiguate only) on Windows so shifted printable
keys are delivered as raw characters instead of being silently eaten.
Also adds a defensive SHIFT_MAP fallback in decodeKittyPrintable for
terminals that send CSI-u sequences with the shift modifier but omit
the shifted_key secondary codepoint.
Measured each animated Loader paint and recursively scheduled the next frame with a 10% duty-cycle target, capped at 200ms to retain responsiveness.
Added a regression covering a slow synchronized-output direct-write path and documented the fix.
Fixes#7290
- Add the `app.live.toggle` keybinding defaulted to `Ctrl+L` to start or stop live voice mode.
- Remap the default display-reset action (`app.display.reset`) from `Ctrl+L` to `Alt+L`.
- Update the live visualizer to listen for stop keys so the toggle chord terminates active sessions.
Cached one stable layout representative per frame display width so same-width animation retains the fast path while width transitions rewrap before painting. Added coverage for wider custom frames remaining within terminal bounds.
(cherry picked from commit 3aa173a574538d754e68f8d10f7b88d437709884)