Skip to content

feat(tui): FR-TUI-P polish + bugfixes (muted palette, hero, metric strip, SIGWINCH, attach hardening) - #268

Merged
linhdmn merged 6 commits into
mainfrom
feat/tui146-polish
Sep 9, 2026
Merged

feat(tui): FR-TUI-P polish + bugfixes (muted palette, hero, metric strip, SIGWINCH, attach hardening)#268
linhdmn merged 6 commits into
mainfrom
feat/tui146-polish

Conversation

@linhdmn

@linhdmn linhdmn commented Sep 9, 2026

Copy link
Copy Markdown
Member

Closes #146.

Implements all 12 FR-TUI-P items as a pure-Go change confined to internal/tui/ (+ docs/TUI.md). No new runtime deps.

What changed (FR-TUI-P-01..12)

  • P-01 attach-resume hardeningattachLocked now guarantees resume on every child-death path: nonzero exit (attach exited (N)), signal death (attach child died (signal N)), and panics inside the env (attach crashed: …). The alternate screen is re-entered, raw mode re-armed, the frame full-repainted and a fresh poll fired; the dashboard never process-exits because the attach child died. A synchronous safeDrawLocked before the async poll pins the note on screen before it can be cleared.
  • P-02 poisoned-shape tests — new poisonDaemon httptest server serves arrays-where-objects and objects-where-arrays on /status, /agents, /history, /sessions; FetchSnapshot must normalize/degrade to empty payloads and render without panic.
  • P-03 failed_recent never FAILED — regression tests pin that failed_recent>0 with all panes idle + closed circuit aggregates to IDLE and never paints FAILED (code was already correct; the strip now renders the count as a historical amber Nf recent suffix beside live active counts).
  • P-04 SIGWINCHLoopEnv.Sigwinch() added (nil-able, like Sigint); TermEnv subscribes signal.Notify(SIGWINCH); the loop repaints promptly on resize instead of waiting for the next 2s poll. Run-level test mutates cols and fires the channel, asserting the sanctioned reflow full-clear.
  • P-05 hero line — new heroLines: the selected (or first) running pane's id/phase/elapsed/worker with an indeterminate pulse bar driven by the spinner frame — no fabricated percent (the snapshot carries no fraction field; issue open-question 1 resolved to indeterminate). Idle shows a next-action cue. Folded with the loop-phase iteration row.
  • P-06 dense metric strip — one row: queue meter + Np/Nc/Nd, live runs, activity sparkline; uptime/herdr/visibility demoted to the dim tail.
  • P-07 worker cards — kept (chip/title/elapsed/attach-hint/▸ already present; trim pinned by existing selection test).
  • P-08 narrow stacking — below 80 columns worker/queued cards stack full-width instead of crushing 2-up; ≥80 keeps 2-up. Overflow pinned at 78 cols.
  • P-09 muted paletteansi.go rewritten: rebindable SGR vars resolving to pilot's chart colors (steel #7eb8da, sage #7ec699, rose #d48a8a, amber #e0af68, slate #3d4450, gray) under COLORTERM=truecolor|24bit, with a 16-color fallback otherwise. Magenta retired. StatusColor/ChipFor carry the palette to every card.
  • P-10 redraw guarantees — tests pin: identical consecutive frames emit zero row writes (no 2J), a one-row change rewrites exactly that row; the resize full-clear is the loop's one sanctioned clear.
  • P-11 wide-glyph clamps — covered by existing ClampLine/VisibleLen CJK/fullwidth/astral tests (still green).
  • P-12 footer/help — footer hint folds by exact width tiers (full ≥116, mid ≥96, compact ≥62, else help/quit) so [q] quit is never clamped off — the full hint previously overflowed the default 100-col terminal. The ? help overlay keeps its bottom rows, so the quit row is visible even at 24×80 (pinned at 24×80 and 10 rows).

Evidence

$ go test ./internal/tui/ -count=1
ok  	github.com/FreePeak/devagent/internal/tui	2.403s

$ gofmt -l internal/tui/   # empty
$ go vet ./internal/tui/   # clean

20 new contract tests in polish_contract_test.go (P-01/02/03/04/05/08/10/12) + existing suite green. docs/TUI.md gains the Layout & visual language (FR-TUI-P) section (layout diagram, palette table, attach-resume + redraw contracts) and the Architecture table note on the sanctioned resize clear.

…h resume (#146)

- FR-TUI-P-09: resolve the muted chart palette (steel/sage/rose/amber/slate)
  at init; truecolor when COLORTERM advertises it, 16-color fallback
  otherwise. Magenta retired; Border/Steel slots added.
- FR-TUI-P-04: LoopEnv.Sigwinch + TermEnv subscription; the loop repaints
  promptly on resize instead of waiting for the next poll.
- FR-TUI-P-01: attach child death (signal, nonzero exit, env panic) now
  always resumes the dashboard — never process-exits.
…146)

- FR-TUI-P-05: hero line for the running work (id/phase/elapsed/worker +
  indeterminate pulse bar; no fabricated percent) or a next-action cue when
  idle; loop-phase iteration row folded in.
- FR-TUI-P-06: metric strip is one dense row — queue meter p/c/d, live run
  counts (failed_recent rendered as historical, never FAILED per P-03),
  activity sparkline; uptime/herdr/vis demoted to the dim tail.
- FR-TUI-P-08: below 80 columns worker cards stack full-width instead of
  crushing 2-up.
- FR-TUI-P-12: the help overlay keeps its bottom rows (quit row always
  visible, pinned by a 24x80 test); the footer hint folds below 80 columns
  so hint + note share the single footer line.
@linhdmn
linhdmn merged commit d81ea2a into main Sep 9, 2026
3 of 7 checks passed
linhdmn added a commit that referenced this pull request Sep 9, 2026
… Q47 resolved, FR-TUI-04/22.2 updated, footer stamp (PRs #265-#268)
@linhdmn
linhdmn deleted the feat/tui146-polish branch September 9, 2026 08:42
linhdmn added a commit that referenced this pull request Sep 9, 2026
…269)

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.
linhdmn added a commit that referenced this pull request Sep 9, 2026
… embedded selector (#270)

Two CI-Go legs have been red on main since the Tauri app (#267) and TUI
polish (#268) landed:

1. Single-implementation gate: app-build.yml legitimately invokes pnpm
   (Tauri 2 webview UI, issue #181 / PRD §20.4 decision) — the gate's
   Go-only rule covers the DevAgent core, so exclude that one workflow's
   lines from the grep instead of weakening the gate itself.

2. staticcheck QF1008: polish_contract_test.go:323 used the embedded
   bufEnv selector; winchEnv promotes cols, so env.cols is identical.

The TestApplyKeysApproveSheet CI-only failure (passes locally 30+ runs on
the same SHA) is filed separately with full analysis.
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.

PRD: TUI polish + bugfix — Pilot/htop/Claude Code visual bar (FR-TUI-P)

1 participant