fix: worktree session UI safety and visibility (review)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 20:49:12 -04:00
parent 9efa270422
commit ace537e3d6
3 changed files with 32 additions and 15 deletions
+12 -6
View File
@@ -287,8 +287,15 @@ class HqtApp(App):
async def _open() -> None: async def _open() -> None:
# is_git_repo is async; resolve it before pushing so the dialog can # is_git_repo is async; resolve it before pushing so the dialog can
# disable the worktree control for non-repo projects. # disable the worktree control for non-repo projects. This worker is
# run raw (not via _run_service_worker), so it must never raise: any
# failure (e.g. git not on PATH) falls back to False, which simply
# disables the worktree checkbox in the dialog.
try:
is_git_repo = await worktree.is_git_repo(Path(project_path)) is_git_repo = await worktree.is_git_repo(Path(project_path))
except Exception as exc: # noqa: BLE001 - keep the worker from crashing the TUI
log.warning("is_git_repo check failed for %s: %s", project_path, exc)
is_git_repo = False
self.push_screen(NewSessionScreen(harness_names, is_git_repo), on_dismiss) self.push_screen(NewSessionScreen(harness_names, is_git_repo), on_dismiss)
self.run_worker(_open()) self.run_worker(_open())
@@ -343,11 +350,10 @@ class HqtApp(App):
parts.append("uncommitted changes") parts.append("uncommitted changes")
if state and state.unique_commits > 0: if state and state.unique_commits > 0:
parts.append(f"{state.unique_commits} unmerged commit(s)") parts.append(f"{state.unique_commits} unmerged commit(s)")
warning = ( warning = None
" and ".join(parts).capitalize() + " — work will be lost" if parts:
if parts joined = " and ".join(parts)
else None warning = joined[:1].upper() + joined[1:] + " — work will be lost"
)
def on_dismiss(result: tuple[bool, bool] | None) -> None: def on_dismiss(result: tuple[bool, bool] | None) -> None:
if result is None: if result is None:
+8 -3
View File
@@ -37,9 +37,14 @@ def format_session_text(
) -> str: ) -> str:
color = _STATUS_COLORS.get(status_text, "#c6d0f5") # default: Text color = _STATUS_COLORS.get(status_text, "#c6d0f5") # default: Text
name = nickname name = nickname
# Mark worktree sessions with their branch. The nickname defaults to the # Worktree sessions always carry the ⎇ marker so they're visually distinct
# branch at creation, so only append the marker when it adds information. # from plain sessions. The nickname defaults to the branch at creation, so
if worktree_branch and nickname != worktree_branch: # when they match we show the glyph once (no duplicated branch); when they
# differ we show both so the branch is still visible.
if worktree_branch:
if nickname == worktree_branch:
name = f"{nickname}"
else:
name = f"{nickname}{worktree_branch}" name = f"{nickname}{worktree_branch}"
label = escape(f"{name} [{harness_name}]") label = escape(f"{name} [{harness_name}]")
return f"[{color}]{symbol}[/] {label} {status_text}" return f"[{color}]{symbol}[/] {label} {status_text}"
+10 -4
View File
@@ -1404,18 +1404,24 @@ async def test_confirm_delete_cancel_returns_none():
def test_format_session_text_appends_worktree_branch_marker(): def test_format_session_text_appends_worktree_branch_marker():
"""nickname != branch → show both nickname and branch around the ⎇ glyph."""
from hqt.tui.widgets.session_list import format_session_text from hqt.tui.widgets.session_list import format_session_text
text = format_session_text("mywork", "claude", "idle", "", "feature-x") text = format_session_text("mywork", "claude", "idle", "", "feature-x")
assert "⎇ feature-x" in text assert "mywork ⎇ feature-x" in text
def test_format_session_text_no_marker_when_nickname_equals_branch(): def test_format_session_text_marker_shows_once_when_nickname_equals_branch():
"""Avoid duplication: when nickname already equals the branch, no marker.""" """nickname == branch (the common case) → ⎇ still appears, glyph once, no
duplicated branch name."""
from hqt.tui.widgets.session_list import format_session_text from hqt.tui.widgets.session_list import format_session_text
text = format_session_text("feature-x", "claude", "idle", "", "feature-x") text = format_session_text("feature-x", "claude", "idle", "", "feature-x")
assert "" not in text assert "" in text
# Glyph appears exactly once, and the branch is not duplicated.
assert text.count("") == 1
assert "⎇ feature-x" in text
assert "feature-x ⎇" not in text
def test_format_session_text_no_marker_for_plain_session(): def test_format_session_text_no_marker_for_plain_session():