From 86f02d8d7148c5fee192e71de40a4b7e98f40e47 Mon Sep 17 00:00:00 2001 From: Jorge Date: Fri, 17 Apr 2026 21:45:50 +0930 Subject: [PATCH] refactor(cli): align model picker viewport with PR #11260 vocabulary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Match the row-budget naming introduced in PR #11260 for the approval and clarify panels: rename chrome_reserve=14 into reserved_below=6 (input chrome below the panel) + panel_chrome=6 (this panel's borders, blanks, and hint row) + min_visible=3 (floor on visible items). Same arithmetic as before, but a reviewer reading both files now sees the same handle. Compact-chrome mode is intentionally not adopted — that pattern fits the "fixed mandatory content might overflow" shape of approval/clarify (solved by truncating with a marker), whereas the picker's overflow is already handled by the scrolling viewport. --- cli.py | 18 ++++++++++-------- .../hermes_cli/test_model_picker_viewport.py | 19 +++++++++---------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/cli.py b/cli.py index 9855327e95..2709b905a6 100644 --- a/cli.py +++ b/cli.py @@ -4520,16 +4520,18 @@ class HermesCLI: scroll_offset: int, n: int, term_rows: int, - chrome_reserve: int = 14, + reserved_below: int = 6, + panel_chrome: int = 6, + min_visible: int = 3, ) -> tuple[int, int]: - """Resolve (scroll_offset, visible_count) for the /model picker panel. + """Resolve (scroll_offset, visible) for the /model picker viewport. - ``term_rows - chrome_reserve`` caps how many rows the panel may use for - items; when the list overflows we slide the offset to keep ``selected`` - on screen. The position counter sits in the bottom border, so no extra - row is reserved for it. + ``reserved_below`` matches the approval / clarify panels — input area, + status bar, and separators below the panel. ``panel_chrome`` covers + this panel's own borders + blanks + hint row. The remaining rows hold + the scrollable list, with the offset slid to keep ``selected`` on screen. """ - max_visible = max(3, term_rows - chrome_reserve) + max_visible = max(min_visible, term_rows - reserved_below - panel_chrome) if n <= max_visible: return 0, n visible = max_visible @@ -9537,7 +9539,7 @@ class HermesCLI: from prompt_toolkit.application import get_app term_rows = get_app().output.get_size().rows except Exception: - term_rows = shutil.get_terminal_size((80, 24)).lines + term_rows = shutil.get_terminal_size((100, 24)).lines scroll_offset, visible = HermesCLI._compute_model_picker_viewport( selected, state.get("_scroll_offset", 0), len(choices), term_rows, ) diff --git a/tests/hermes_cli/test_model_picker_viewport.py b/tests/hermes_cli/test_model_picker_viewport.py index 161d15eed8..4f56ee8043 100644 --- a/tests/hermes_cli/test_model_picker_viewport.py +++ b/tests/hermes_cli/test_model_picker_viewport.py @@ -19,16 +19,15 @@ class TestPickerViewport: assert visible == 5 def test_long_list_caps_visible_to_chrome_budget(self): - # 36 models, 30 terminal rows, chrome_reserve=14 → max_visible=16. - # Position counter lives in the bottom border, no row reserved. + # 30 rows minus reserved_below=6 minus panel_chrome=6 → max_visible=18. offset, visible = _compute(selected=0, scroll_offset=0, n=36, term_rows=30) - assert visible == 16 + assert visible == 18 assert offset == 0 def test_cursor_past_window_scrolls_down(self): - offset, visible = _compute(selected=20, scroll_offset=0, n=36, term_rows=30) - assert visible == 16 - assert 20 in range(offset, offset + visible) + offset, visible = _compute(selected=22, scroll_offset=0, n=36, term_rows=30) + assert visible == 18 + assert 22 in range(offset, offset + visible) def test_cursor_above_window_scrolls_up(self): offset, visible = _compute(selected=3, scroll_offset=15, n=36, term_rows=30) @@ -36,16 +35,16 @@ class TestPickerViewport: assert 3 in range(offset, offset + visible) def test_offset_clamped_to_bottom(self): - # Selected on last item — offset must keep visible window full, not - # walk past the end of the list. + # Selected on the last item — offset must keep the visible window + # full, not walk past the end of the list. offset, visible = _compute(selected=35, scroll_offset=0, n=36, term_rows=30) assert offset + visible == 36 assert 35 in range(offset, offset + visible) def test_tiny_terminal_uses_minimum_visible(self): - # term_rows below chrome_reserve falls back to the floor of 3 rows. + # term_rows below the chrome budget falls back to the floor of 3 rows. _, visible = _compute(selected=0, scroll_offset=0, n=20, term_rows=10) - assert visible == 3 # max(3, 10 - 14) == 3 + assert visible == 3 def test_offset_recovers_after_stage_switch(self): # When the user backs out of the model stage and re-enters with