- SIGWINCH doesn't always fire on initial spawn — the TUI starts up thinking it has 0 columns and emits garbage until the first real resize. Fix: synthesize an ioctl(TIOCSWINSZ) before the first read, and re-send on focus events. - xterm.js negotiates dimensions with the PTY backend over a non-obvious dance; off-by-one in the cell math wraps long prompts in the wrong place every time. - Tools that detect "am I in a TTY" via isatty() behave differently from tools that stat() stdin; a few agents fall through to non-TUI mode if the PTY's mode bits aren't quite right.
None of that is reflected in the abstract "PTY is a virtual terminal" mental model. The kernel/terminal/application split is a leaky abstraction in practice — you only find out by hosting one inside the other.