Skip to content

fix(terminal): keep PTY and Ghostty resize ordering in lockstep - #5320

Closed
StiensWout wants to merge 7 commits into
pingdotgg:mainfrom
StiensWout:t3code/fix-terminal-resize-ordering
Closed

StiensWout wants to merge 7 commits into
pingdotgg:mainfrom
StiensWout:t3code/fix-terminal-resize-ordering

Conversation

@StiensWout

@StiensWout StiensWout commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Queue a server-side flush sentinel so resize acknowledgements follow all previously queued PTY output.
  • Return the covered attach-stream sequence in each resize acknowledgement, and wait for that exact sequence before applying Ghostty dimensions.
  • Gate Ghostty grid changes on accepted PTY dimensions with single-flight desired-size retries and safe disposal.
  • Hold initial terminal history/output until the first accepted grid so old-width bytes cannot be replayed as duplicate lines during resize.
  • Prefill the opaque terminal canvas with the theme background before font/WASM initialization.

Validation

  • Server ordering tests: 3 passed.
  • Focused web terminal tests: 46 passed.
  • Contract tests: 23 passed; client-runtime terminal state tests: 6 passed.
  • Server, contracts, client-runtime, and web typechecks: passed.
  • Focused lint for touched terminal files: passed.

Actual T3 preview

The GIF below is captured from the real T3 Code UI and terminal drawer on this branch while resizing wide → narrow → wide. It contains no synthetic frame or added border:

T3 terminal resize proof

This intentionally does not include terminal open/close reconciliation or Ctrl+W handling.


Note

Medium Risk
Resize RPCs now block until output drains, and synchronous resize-from-listener paths are sensitive; changes touch core terminal I/O ordering across server and web renderer.

Overview
Terminal resize is now ordered end-to-end so PTY width and Ghostty grid stay aligned during drawer resize and streaming output.

Contracts & client state: resize returns TerminalResizeResult with an attach-stream sequence instead of void. Terminal session/buffer state tracks sequence alongside version so the UI knows which output events have been applied.

Server (TerminalManager): Before acknowledging a resize, the manager queues a flush sentinel on the PTY output drain, publishes all prior queued output, and returns the covered eventSequence. Flush sentinels are released on queue disposal (including exit) to avoid hangs; tests cover ordering, listener-triggered resize deadlock, and exit during a blocked drain.

Web UI: TerminalWriteBarrier waits until React has applied output up to the resize acknowledgement’s sequence before and after runTerminalResize. GhosttyTerminalSurface starts at a 1×1 grid, buffers initial history/output until the first accepted PTY resize, uses async onResize with single-flight requests and retries, and prefills the opaque canvas with the theme background during async init.

Reviewed by Cursor Bugbot for commit 55f52f5. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Keep PTY and Ghostty resize ordering in lockstep by sequencing resize acknowledgements

  • Introduces TerminalResizeResult (with a sequence field) as the return type for resize RPCs, replacing void, so callers know which output event the PTY had processed at acknowledgement time.
  • The server's TerminalManager.resize now queues a flush sentinel and waits for all in-flight output to be published before returning, ensuring the sequence number reflects output order.
  • The Ghostty surface (GhosttyTerminalSurface) buffers writes until the first resize is acknowledged, applies grid changes only on accepted PTY resizes, and retries on unchanged-dimension rejection to avoid jitter.
  • A new client-side TerminalWriteBarrier in ThreadTerminalDrawer gates grid changes until the corresponding output sequence has been applied to the terminal buffer.
  • Sequence numbers are now tracked end-to-end in TerminalSessionState and TerminalBufferState via nextTerminalSequence.
  • Risk: resize no longer returns immediately — it suspends until queued output drains, which could block callers if the drain stalls (guarded by deadlock detection for synchronous resize-from-listener patterns).

Macroscope summarized 55f52f5.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e6e75c58-6047-42c8-b019-8f4f3d013cd3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched Author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 4, 2026
Comment thread apps/server/src/terminal/Manager.ts Resolved
@StiensWout
StiensWout marked this pull request as ready for review August 4, 2026 06:43
@macroscopeapp

macroscopeapp Bot commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR fundamentally changes terminal resize synchronization between PTY and Ghostty, introducing new coordination mechanisms (flush sentinels, write barriers, acknowledgement-based grid sizing) across both server and client. While the tests are comprehensive, the significant runtime behavior changes warrant human review.

You can customize Macroscope's approvability policy. Learn more.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c425f1d894604c039c0cc2372ec2346b1b8776c6. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched Author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant