emrg: guard TUI terminal size probe against 0x0 winsize - #1080
Merged
Conversation
argszero
commented
Aug 31, 2026
argszero
left a comment
Owner
Author
There was a problem hiding this comment.
✅ LGTM — cycle
Independent review of this cycle:
- Root-cause chain verified: os.get_terminal_size() returns 0x0 (no exception) when the PTY winsize isn't reported yet → width=0 overwrites the 80x24 default → ctx.width=0 → available=max(1, -2)=1 → every CJK char (cell_len=2) split onto its own line. 'Resize once fixes it' matches the SIGWINCH re-probe path.
- Fix: shutil.get_terminal_size(fallback=(80,24)) in _probe_terminal (rejects 0 values — 0 < col < 255 guard); handle_resize falls back to last-known-good dims instead of the defaults, so a premature SIGWINCH cannot shrink the layout. Covers the Windows 500ms poll path too (app.py → handle_resize).
- Tests: both new tests exercise the 0x0 monkeypatch path — probe → 80x24 fallback; resize → keeps 120x40. shutil's internal exception+range guard makes the fallback deterministic.
- CI green: test + test-windows (run 33355317364), incl. actionlint + doc-count guard; Agent.md 1178→1180 synced. Local: pytest 1179 passed + 1 skipped.
argszero
commented
Aug 31, 2026
argszero
left a comment
Owner
Author
There was a problem hiding this comment.
✅ LGTM — cycle (2/3)
Independent re-verification this cycle (distinct from the 1/3 cycle):
- Head byte-identical to the 1/3 review (379096e) — no force-push, no history rewrite.
- CI still green: test + test-windows pass (run 33355317364), incl. actionlint gate + doc-count guard.
- Behavior re-confirmed live: with os.get_terminal_size() monkeypatched to 0x0, shutil.get_terminal_size(fallback=(80,24)) returns columns=80 lines=24 — the guard deterministically rejects 0.
- Branch file check: tests/test_terminal_render.py has the 2 new tests (7 total vs 5 on master), exercising both the probe fallback (80x24) and resize last-known-good (120x40) paths.
- MERGEABLE / CLEAN. No ❌ in between. 2 consecutive LGTMs from distinct cycles.
argszero
commented
Aug 31, 2026
argszero
left a comment
Owner
Author
There was a problem hiding this comment.
✅ LGTM — cycle (3/3)
Third consecutive LGTM from a distinct evolution cycle:
- Head byte-identical 379096e (no force-push / history rewrite since 1/3).
- Diff re-verified against master: exactly 3 files (Agent.md 1178→1180 doc-count sync, terminal.py shutil guard in _probe_terminal + last-known-good fallback in handle_resize, +2 tests) — 62 insertions / 13 deletions, no scope creep.
- CI green: test + test-windows (run 33355317364), actionlint + doc-count guard included.
- MERGEABLE / CLEAN. No ❌ between LGTMs.
Merge condition met (3 consecutive ✅ from different cycles).
argszero
added a commit
that referenced
this pull request
Aug 31, 2026
…d, GUI tool/text order, LLM stream retry, session message_count) (#1085) Co-authored-by: EMRG Evolution <emrg@argszero.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Host-reported bug (rant 2026-08-31T11:36:22): typing Chinese in the TUI right after opening macOS Terminal still misaligns ("中文错行") even after PR #1071 — and resizing the window once fixes it. That pointed at a terminal-size initialization race, a different root cause than #1071's row-count overflow.
Root cause (evidence chain)
os.get_terminal_size()returnsos.terminal_size(columns=0, lines=0)when the PTY winsize has not been reported yet (macOS Terminal at startup) — it does not raise, so the existingexcept (OSError, ValueError)guard never fires._probe_terminal()(emrg/client/python_tui/terminal.py) blindly overwrites the 80×24 default with those 0s →caps.width=0→viewport.resize→viewport_width=0→RenderContext.width=0.InputWidget.render,available = max(1, ctx.width - len(prompt)) = max(1, 0-2) = 1. Every CJK char hascell_len=2 > 1, so the wrap loop breaks immediately andend == pos → end = pos+1— each Chinese character is rendered on its own line, blowing up the composer height.handle_resize()had the same unguarded path.Fix
_probe_terminal(): useshutil.get_terminal_size(fallback=(80, 24))— it rejects 0 values (guard0 < columns < 255) and falls back to COLUMNS/LINES env then the explicit fallback, never returning 0×0.handle_resize(): same probe but falling back to the last known-good dimensions (self.caps), so a premature SIGWINCH cannot shrink the layout either.Verification
uv run pytest tests/→ 1179 passed + 1 skipped (1180 total, Agent.md doc-count synced 1178 → 1180)