Skip to content

fix(terminal): emit DEC 2048 in-band size reports#311

Merged
forketyfork merged 3 commits into
mainfrom
fix/agent-scoped-resize-holds
May 18, 2026
Merged

fix(terminal): emit DEC 2048 in-band size reports#311
forketyfork merged 3 commits into
mainfrom
fix/agent-scoped-resize-holds

Conversation

@forketyfork
Copy link
Copy Markdown
Owner

@forketyfork forketyfork commented May 18, 2026

Solution

After Architect started answering DECRQM mode queries (commit bde3b89), apps that opt into DEC mode 2048 in-band size reports stopped reflowing on grid/full view toggle and window resize. nvim is the case this was diagnosed against: it sees Architect's positive 2048 response, enables the mode, and then waits for CSI 48 ; rows ; cols ; px_h ; px_w t reports that the terminal never emits. SIGWINCH still fires; nvim's TUI layer defers to the in-band channel that Architect was silently failing to honor.

This PR fixes the root cause by emitting the mode 2048 report when the app enables the mode and after every PTY/VT resize, matching ghostty's src/termio/Termio.zig:sizeReportLocked mode_2048 branch.

With that addressed, several layers of resize-related code added earlier on this branch are no longer needed:

  • Manual kill(-pgrp, SIGWINCH) after TIOCSWINSZ, and the focus-in / second SIGWINCH / Ctrl-L nudge ladder for vim-family processes
  • Slave-side TIOCSWINSZ fallback and ttyname tracking in pty.zig
  • Agent-scoped output hold mechanism: synchronized-output hold, terminal-resize hold, hold-agent fields, detectOutputHoldAgent
  • Agent-frame-delay branch in Expanding/Collapsing animation completion
  • outputHoldActive / shouldHoldSessionCacheRefresh / renderHeldSessionTexture in the renderer
  • Resize-trace diagnostic plumbing across pty.zig / session/state.zig / app/layout.zig / app/runtime.zig

The PTY layer is now ghostty-shaped: pty.setSize is a single ioctl(master, TIOCSWINSZ), dup2 runs before childPreExec, childPreExec closes the original master and slave fds after TIOCSCTTY, and childPreExec no longer touches the SIGWINCH disposition.

expireSynchronizedOutput is kept (without agent scoping) as a stuck-mode safety net for apps that enter synchronized output and never end it.

Net: +113 / −284 vs main.

Test plan

  • Open nvim in a session, toggle grid → full → grid. nvim reflows to the new dimensions immediately, no keystroke required.
  • Drag the Architect window to resize it while nvim is open. nvim reflows.
  • Run nvim --clean somefile.txt and repeat the toggle. Behavior matches the regular config.
  • Toggle grid/full with plain shells (no editor running). Prompts reflow.
  • Toggle grid/full with Codex or Claude Code. Output history reflows at the new width.

@forketyfork forketyfork force-pushed the fix/agent-scoped-resize-holds branch from 6262be5 to 75fe4dd Compare May 18, 2026 06:55
@forketyfork forketyfork changed the title fix(terminal): scope resize holds to agent sessions fix(terminal): stabilize agent resize holds May 18, 2026
@forketyfork forketyfork requested a review from Copilot May 18, 2026 07:07
@forketyfork forketyfork marked this pull request as ready for review May 18, 2026 07:07
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75fe4ddfd2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/session/state.zig Outdated
Comment thread src/session/state.zig Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR narrows terminal resize and synchronized-output “output hold” behavior so stale-texture cache reuse only applies to AI-agent sessions (Codex/Claude/Gemini), restoring live repaint behavior for normal TUIs (e.g., nvim) during SIGWINCH resizes.

Changes:

  • Adds agent ownership tracking for synchronized-output and terminal-resize holds, and only treats holds as active when an agent is associated.
  • Delays PTY/VT resize by one frame after agent grid→full expansion so a stable full-mode cache frame exists for the hold to display.
  • Updates terminal resize path to start resize holds only when an agent session is detected; updates docs and tests accordingly.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/session/state.zig Tracks which agent owns output holds; gates hold activation/expiry logic on agent ownership; adds detection helper + tests.
src/app/runtime.zig Adds one-frame delay of terminal layout resize after agent expansion to populate a full-mode cache frame first; adds test.
src/app/layout.zig Starts terminal resize holds only when detectOutputHoldAgent() identifies an agent session.
docs/ARCHITECTURE.md Documents agent-scoped holds and the pre-resize full-frame behavior for agent expansions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/session/state.zig Outdated
@forketyfork forketyfork force-pushed the fix/agent-scoped-resize-holds branch 5 times, most recently from 8b8fae1 to 836189a Compare May 18, 2026 08:49
@forketyfork forketyfork force-pushed the fix/agent-scoped-resize-holds branch from 836189a to 390f2f2 Compare May 18, 2026 08:59
Issue: After Architect started answering DECRQM mode queries (commit
bde3b89), apps that opt into DEC mode 2048 stopped reflowing on grid/full
view toggle and window resize. nvim is the most visible case: it treats a
positive 2048 response as a contract that the terminal will send
`CSI 48 ; rows ; cols ; px_h ; px_w t` whenever geometry changes.
Architect responded to the query but never emitted the reports, so those
apps deferred to an in-band channel that never arrived.

Solution: Emit the mode 2048 size report when the app first enables the
mode and after every PTY/VT resize, matching ghostty's sizeReportLocked.
With the root cause addressed, the layered workarounds added earlier on
this branch are no longer needed and are removed: manual
kill(-pgrp, SIGWINCH), the focus-in / second SIGWINCH / Ctrl-L nudge
ladder, slave-side TIOCSWINSZ fallback, agent-scoped output holds, the
agent-frame-delay in animation completion, the held-texture path in the
renderer, and the resize-trace diagnostics. The spawn path is aligned
with ghostty: dup2 before childPreExec, close master/slave fds inside
childPreExec after TIOCSCTTY, no SIGWINCH disposition reset.
@forketyfork forketyfork changed the title fix(terminal): stabilize agent resize holds fix(terminal): emit DEC 2048 in-band size reports May 18, 2026
@forketyfork forketyfork marked this pull request as draft May 18, 2026 13:13
@forketyfork forketyfork marked this pull request as ready for review May 18, 2026 13:18
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee3337329b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/app/layout.zig Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment thread src/shell.zig Outdated
Comment thread src/app/layout.zig Outdated
Comment thread src/session/state.zig
Issue: Four unresolved review threads on PR #311 flagged genuine
problems: a forked child branch that could unwind back to the parent on
childPreExec error, duplicate logging of resize failures, missing DEC
2048 reports on pixel-only resizes, and a foreground-pgrp lookup
duplicated between detectForegroundAgent and foregroundPgrp.

Solution: In the child branch of Shell.spawn, swap the bare `try` for
`catch std.c._exit(1)` so a childPreExec error terminates the child
instead of returning to the runtime. In applyTerminalResize, drop the
std.debug.print duplicates and route failures through log.warn only;
compare the full winsize struct so the DEC 2048 in-band report fires
on pixel-only resizes too while the VT-resize stays gated on cell
count. detectForegroundAgent now calls foregroundPgrp for the
sysctl/tcgetpgrp fallback, eliminating the duplicated lookup. Two
review threads about agent-scoped output hold staleness are left as
won't-fix in this PR because the entire output-hold mechanism is
removed in the follow-up.
@forketyfork forketyfork merged commit 6c1f67f into main May 18, 2026
4 checks passed
@forketyfork forketyfork deleted the fix/agent-scoped-resize-holds branch May 18, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants