From 577fa6ade047c08c5f43991fb6a44befaf84a9bd Mon Sep 17 00:00:00 2001 From: "linh.doan" Date: Wed, 9 Sep 2026 16:23:27 +0700 Subject: [PATCH] =?UTF-8?q?fix(tui):=20move=20Sigwinch=20behind=20unix=20b?= =?UTF-8?q?uild=20constraints=20=E2=80=94=20windows=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #268 shipped TermEnv.Sigwinch using syscall.SIGWINCH with no build tag, which does not exist on windows: CI-Go windows-build/windows-cross and Release have been red since 74b3203 (same class as the 5d79ab0 release-gate lesson; #268 merged before its windows CI completed). Move the implementation into rawterm_unix.go (darwin||linux, already the termios home) and add a nil-channel stub in rawterm_other.go — the TermEnv contract (loop.go:111-114 'may be nil') already covers it: Run's resize select never fires and the poll path repaints. Verified: GOOS=windows go build ./... rc=0, go build rc=0, go vet clean, internal/tui suite green on darwin. --- internal/tui/loopimpl.go | 8 -------- internal/tui/rawterm_other.go | 12 +++++++++++- internal/tui/rawterm_unix.go | 12 ++++++++++++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/internal/tui/loopimpl.go b/internal/tui/loopimpl.go index b6ccf1a..0191e64 100644 --- a/internal/tui/loopimpl.go +++ b/internal/tui/loopimpl.go @@ -1085,14 +1085,6 @@ func (e *TermEnv) Sigint() <-chan os.Signal { return sig } -// Sigwinch subscribes to terminal resizes (FR-TUI-P-04) so the loop can -// re-probe the geometry and repaint promptly instead of at the next poll. -func (e *TermEnv) Sigwinch() <-chan os.Signal { - sig := make(chan os.Signal, 1) - signal.Notify(sig, syscall.SIGWINCH) - return sig -} - // SuspendAttach runs `herdr --session agent attach ` with // inherited stdio, exactly what `devagent attach --exec` does // (FR-VIS-02). The resolved pane id is recorded in the orchestration ledger diff --git a/internal/tui/rawterm_other.go b/internal/tui/rawterm_other.go index d529ed2..28abb43 100644 --- a/internal/tui/rawterm_other.go +++ b/internal/tui/rawterm_other.go @@ -2,7 +2,10 @@ package tui -import "errors" +import ( + "errors" + "os" +) // rawTerm is a no-op stub on platforms without the POSIX termios interface: // the interactive loop refuses to start (the non-TTY one-shot path never @@ -16,3 +19,10 @@ func (r *rawTerm) enterRaw() error { return errors.New("raw mode unsupported on func (r *rawTerm) restore() {} func termSize(fd int) (rows, cols int) { return DefaultRows, DefaultColumns } + +// Sigwinch is a stub on platforms without SIGWINCH (Windows). The TermEnv +// contract (loop.go) allows a nil channel: Run's resize select simply never +// fires and the poll path repaints instead. +func (e *TermEnv) Sigwinch() <-chan os.Signal { + return nil +} diff --git a/internal/tui/rawterm_unix.go b/internal/tui/rawterm_unix.go index 002560f..d2180c5 100644 --- a/internal/tui/rawterm_unix.go +++ b/internal/tui/rawterm_unix.go @@ -9,6 +9,8 @@ package tui // syscall — the same IFMIN..IFLAG word layout IoctlGetTermios manages. import ( + "os" + "os/signal" "syscall" "unsafe" ) @@ -78,3 +80,13 @@ func termSize(fd int) (rows, cols int) { } return int(ws.Row), int(ws.Col) } + +// Sigwinch subscribes to terminal resizes (FR-TUI-P-04) so the loop can +// re-probe the geometry and repaint promptly instead of at the next poll. +// Unix-only: syscall.SIGWINCH does not exist on Windows — the TermEnv +// contract (loop.go: may return nil) covers the stub there. +func (e *TermEnv) Sigwinch() <-chan os.Signal { + sig := make(chan os.Signal, 1) + signal.Notify(sig, syscall.SIGWINCH) + return sig +}