mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 09:19:42 +02:00
c614241c4838023fe4849f05c2fb5d43fb64876f
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
eb5d982c38 |
fix(tiles): refresh fetches first, then resets in-stream and replays
A tile's refresh (a {t:'r'} or {t:'c'} frame, every reconnect) wiped the
pane with a synchronous xterm clear() at the load's turn, BEFORE its fetch,
and wrote live frames straight through the fetch and the replay. That is
the replay clear CLAUDE.md "Terminal resilience" forbids: bytes still
queued in xterm are parsed after a synchronous clear and fuse into the
snapshot, and clear() keeps the cursor's row, column, SGR and margins, so
the capture (raw rows, no home) started wherever the cursor sat. A failed
or empty fetch left the tile blank.
The refresh now runs in the primary pane's order (_onSessionNeedsRefresh,
_resetTerminalForReplay):
- fetch first, so the tile keeps its last frame through the round trip and
through a grid tile's wait in the load queue;
- from the response on, live frames are held in _liveQueue with their
arrival time, as _pullHistory already did, and the body read of a bounded
window (grid tile, shell) gets the pull's 10 s budget, while Pane B's
unbounded full=1 keeps the request's own budget;
- then the queued in-stream \x1bc immediately before the replay;
- then the held frames that arrived after the response (_flushLiveQueue,
now shared with _pullHistory), then the owed marker.
A failed, aborted or empty fetch writes nothing and resets nothing.
The _stampMarkerIfOwed guard for a pending trailing refresh stays (that
refresh settles the marker itself either way); only its rationale changed.
The fake xterm now treats an in-stream RIS like clear() in its row
emulation.
Tests: the ones that counted clear() calls on the refresh path now count
the in-stream reset instead, assert it sits right before the replay and
that clear() is never called (unit single-flight block, the marker
ordering tests, the reconnect test, the grid {t:'r'} and marker tests, and
the scroll test's server-clear overflow case, which now goes through a
refresh). New: the screen is untouched on a failed or empty fetch and on a
failed body read (held frames written in order), frames before the
response are written through and later ones held behind the replay, the
cutoff drops frames the capture covers, the body budgets, and a grid tile
keeps its last frame through its own capture's round trip.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
||
|
|
a96a94fb7e |
fix(tiles): send a tile's click report ephemeral, review follow-up
The tile's hand-encoded click report went through _handleDesktopTerminalClick and _sendSyntheticSgrTap to _sendInputAsync, so it took a seq, was persisted and would be redelivered after a reload. The documented TerminalTile rule (CLAUDE.md, Split-pane sessions) is that only typed input enters that queue and focus/mouse reports go out ephemeral, and the tile's own _onTerminalData says the same. Before #555 an opencode tile's click went through xterm's encoder and that ephemeral path. A click still unacknowledged when the page reloads, or sent during a server restart, could be replayed onto a later screen, where a press+release can pick a dialog option. _sendSyntheticSgrTap now takes an opt-in `ephemeral` field on its target and sends through _sendInputEphemeral when it is set; _handleDesktopTerminalClick passes the target through unchanged, and TerminalTile._installClickListener sets it. Without the flag nothing changes, so the primary pane's own click and touch tap reports stay on _sendInputAsync exactly as before (whether the primary pane should also go ephemeral is a separate question, out of scope here). Tests: the tile case now requires a frame with no seq and nothing pending in the reliable queue, and the targeted-click case in terminal-touch-tap spies on both send paths: a target with the flag goes ephemeral, an untargeted click and an untargeted tap stay durable. Dropping `ephemeral: true` from the tile, or the branch in _sendSyntheticSgrTap, turns the matching test red. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
24a73ecd81 |
fix(tiles): page a hollow tile only from the live screen, review follow-up
A tile counts as hollow when every row above its screen is its own overflow (baseY minus _overflowRows is 0), so unlike the primary pane, whose hollow buffer has baseY 0, its viewport can sit above the bottom while it is hollow: Shift+PageUp, a scrollbar drag or a wheel during the first replay leave it up there. _maybePageCliTranscript never looked at the viewport, so every wheel, wheel-down included, was turned into PageUp/PageDown and swallowed. xterm never scrolled back, the stale rows stayed on screen while the CLI paged out of view, and clicks were dropped too, because the click report refuses an off-bottom viewport. The tile now pages only while _terminalViewportAtBottom holds for its own terminal, checked before the pending travel is touched. Off the bottom the wheel stays with xterm, so a wheel-down brings the viewport home and paging resumes from there. The primary pane is unchanged: its hollow test already implies a viewport at the bottom, which the twin comment now says. Tests: a unit case for a tile hollow by the discount with its viewport above the bottom (no page key, no preventDefault, and no travel carried over once back home), and the real-browser case now scrolls a hollow tile up and proves a real wheel-down scrolls xterm home with no page key sent, then pages again. Both go red with the gate removed, and the unit case also with the gate moved below the pending-travel update. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
4fe843a94e |
fix(tiles): page a hollow tile's CLI transcript and report its clicks (#555 parity)
#555 made the primary pane page opencode's transcript with PageUp/PageDown from the wheel, because opencode draws in place on the alternate screen and leaves the browser's buffer with no scrollback. A TerminalTile (a grid tile, the split's Pane B) left every wheel to xterm, so in an opencode tile the wheel scrolled nothing, or only stale rows. The tile now runs the primary pane's own gates aimed at itself (its terminal, its session, never the active one): xterm's tracking mode, the Claude forwarding gate, then the hollow-buffer test. A wheel that passes them is consumed in the capture phase and turned into PageUp/PageDown through the shared pageKeysForTravel math, coalesced per tile (40 ms, 512 bytes, the twin of the primary pane's queue) and sent ephemeral on the tile's own socket. Every other wheel stays with xterm as before, the shell history pull included. The file names no CLI: the mode rules stay in terminal-ui.js, and terminal-tile.js joins the frontend no-id-branching guard. A plain port of the primary's baseY === 0 test would almost never fire in a grid. A tile's first capture is taken at the PTY's previous size (usually the taller primary pane's) and written into a shorter xterm, and its own row-shrinking fits (zoom-out, divider drags, tile count changes) push more rows above the screen. The tile counts those rows as its own overflow: all of them after a load whose capture held a single screen (the server's captureRows), plus whatever a local fit or a PTY geometry report pushes up, reset by a clear and clamped to baseY. The paging gate gets baseY minus that count. Output that scrolls real lines still counts as history, so the tile stops paging there. #555's other half, stripping opencode's mouse DECSETs so a drag selects text, is server-side and already reached tile sockets. It also left the tile's xterm unable to encode opencode's clicks, so the tile now installs the primary pane's desktop click report (bubble phase, gated on the session's cliMouseTracking, the tile's own link hover and selection). Both listeners, the flush timer and the page-key state are torn down in destroy(). Still out of scope, as the fileoverview now says: touch paging (tiles have no touch path) and SGR wheel forwarding to Claude's fullscreen renderer (tile-grid-plan follow-up 4), so a fullscreen Claude tile keeps leaving the wheel to xterm. Tests: test/terminal-tile-scroll.test.ts drives a real tile in the vm harness (session targeting, every no-page case, accumulation, the cap, coalescing, byte parity with the primary pane, the overflow discount through a load, a fit, a geometry report and a clear, the click report and destroy); the discount cases fail with it removed. The fake xterm gains opt-in row emulation. test/terminal-tile-scroll.browser.test.ts checks the same model against a real xterm with trusted wheel events (browser suite, not the gate). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |