Commit Graph
3 Commits
Author SHA1 Message Date
timkjrandClaude Opus 5.5 140ca35e2d fix(split-pane): keep the disconnected marker visible, skip detached sessions
Address Ark0N's review on #506:

- The history pull's own `\x1bc` reset erased the "Pane B disconnected"
  marker onclose wrote, painting a fresh, current-looking history while
  onData kept silently dropping every keystroke on the dead socket — a
  Codeman restart drops the socket while the tmux session (and so the HTTP
  pull) survives, making this easy to hit. onclose now tracks the closure
  via `_wsClosed` in addition to writing the marker (extracted into
  `_writeDisconnectedMarker()`), and a replay re-stamps it in the pull's
  `finally` block, after the live-frame flush, whichever order the close
  and the pull land in.
- `_maybeLoadMoreHistory()` now stands aside for a detached session,
  mirroring `_sendResize()`'s existing check and app.js's
  `_maybeRefetchFullHistory()` — its own window already owns its PTY size
  and scrollback.
- Wording: a non-shell CLI's history is out of scope for this pull, not
  absent (codex and Claude's inline renderer do grow tmux history); the
  alternate-screen skip only matters for a direct-PTY shell, since tmux
  never surfaces the alt buffer to the browser xterm. CLAUDE.md points at
  the invariants heading directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 19:59:22 -05:00
timkjrandClaude Opus 5.5 17232b01f6 fix(split-pane): let a Shell Pane B's scroll-up reach tmux history
tmux repaints a burst of output instead of scrolling it, so a shell
pane's xterm keeps about one screen of scrollback while tmux holds every
line. The primary pane goes back for it when the wheel reaches the top;
Pane B is a separate xterm that loaded history once at connect and never
again, so after a `cat` its earlier output was unreachable.

Pane B now does the same for a shell session: wheel-up at the top of the
normal screen pulls ?full=1&tail=TERMINAL_TAIL_SIZE and holds the
reader's place across the replay. The wheel listener is capture-phase
because xterm stopPropagation()s the events it consumes.

It follows the primary pane's rules from #494 and its 1.33.2 merge-time
fixes: a window holding no more rows than the pane (which covers a
downgrade), or a pane already at its `scrollback + rows` cap, is skipped
without a rewrite. That skip backs off to 60 s when the window was
truncated or the pane is full, since each ask costs the server a
whole-history capture-pane; an untruncated window keeps the 4 s cooldown.
There is no truncation banner in Pane B, so the 'tail' relabel does not
apply.

Live frames, a {t:'c'} clear included, are held with their arrival time
while the replay runs and applied in order only if they arrived after the
capture. The fetch has a 10 s deadline since it holds live output while
it runs. The tail of _loadBuffer() becomes _endBufferLoad() so the pull
shares its single-flight bookkeeping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:24:08 -05:00
Codeman maintainer 299a21d5f5 fix(split-pane): merge-time fixes for split-pane sessions (#453)
The maintainer's promised merge-time fixes from the final review of #453:

1. closeSplitPane() tears down a divider drag still in progress, so a split
   that collapses mid-drag no longer leaves body.split-pane-resizing (the
   page-wide col-resize cursor and user-select lock) set until a reload.
2. openSplitPane() re-applies the picker's own exclusions (detached session,
   pid === null, no session record) for a row that went stale while the
   menu sat open, refusing silently like its neighbouring gates.
3. architecture-invariants: the hard-hide of .btn-split is the
   @media (max-width: 1179px) rule in styles.css, not mobile.css.
4. SplitTerminalPane.destroy() nulls onclose (and onerror) beside onopen
   and onmessage.
5. Picker rows drop the data-session-id attribute nothing read.
6. The Pane-A-ends branch collapses with skipPrimaryResize, so the closing
   resize is no longer aimed at the session the server just removed.
7. The {t:'r'} refresh path is single-flight across the fetch and the
   chunked write, coalescing a mid-replay refresh into one trailing re-run.

Tests: split-pane-auto-collapse-unit gains the drag-teardown, exclusion and
skip-resize cases; the new split-pane-terminal-unit covers destroy() and the
refresh single-flight. All were run against the pre-fix module to confirm
they fail there.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit dbd39aed015ae5ae5870aba398bf4b4ab5118e47)
2026-09-21 04:53:19 +02:00