Skip to content

Fix BUG-076: Hera-pane false "Session not running" after ordinary rail nav - #920

Merged
anutron merged 1 commit into
masterfrom
argus/hera-pane-false-detach
Aug 2, 2026
Merged

Fix BUG-076: Hera-pane false "Session not running" after ordinary rail nav#920
anutron merged 1 commit into
masterfrom
argus/hera-pane-false-detach

Conversation

@anutron

@anutron anutron commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Hera coordinator/agent panes intermittently showed "Session not running - press Enter to start" for a session that was genuinely alive moments before, triggered by ordinary rail j/k navigation away and back to a row.
  • Root cause: not a liveness misclassification — the session was really stopped by a legitimate size-drift kick (heraKickRerender, BUG-074), whose auto-restart then unconditionally skipped itself. handleSessionExitUI's "is the user still watching" gate checked only a.mode==modeAgent (the classic fullscreen agent view). The native Hera view never sets that mode — it stays modeTaskList with ActiveTab()==TabHera regardless of which pane is focused. So every kick fired from a Hera pane (nearly every task's first Hera-view bind, since Hera panes are narrower than the main agent view) took the "user navigated away, settle at InReview" branch, even while the operator was watching it live in Hera. The kick itself is async (RPC + QueueUpdateDraw), so the operator sees it fine, glances away for "a moment," and by the time they look back the session has already been stopped and never resumed.
  • Fix: App.isViewingTaskSession(taskID) recognizes both ways of "watching a session" — the classic agent view, or the Hera tab with the task bound to either pane via the new HeraPage.IsBoundToTask. handleSessionExitUI now calls this instead of the inline modeAgent-only check. The kick decision itself (heraKickRerender/ShouldKickRerender) is untouched and correct — only the exit-time restart decision was wrong.

Regression coverage

  • internal/tui/hera/panes_test.go: TestPanes_IsBoundToTask — pure IsBoundToTask semantics (coordinator counts as bound the whole time a worker under it is selected; unrelated/empty task rejected).
  • internal/tui/app_test.go: TestApp_IsViewingTaskSession — all isViewingTaskSession branches (classic agent view, Hera tab with a bound task, Hera tab with an unbound task, Hera binding present but a different tab active).
  • internal/tui/heraactions_test.go: TestHandleSessionExitUI_RerenderRestartsWhenViewedViaHeraPane — end-to-end through a real Hera tab selection + handleSessionExitUI; confirmed to fail with status=in_review against the old modeAgent-only gate before asserting the fixed auto-restart behavior.

Documented as BUG-076 in context/knowledge/gotchas/hera-view.md.

Test plan

  • make build, make vet, make fmt-check, make lint-pr all clean.
  • make vuln fails on 3 pre-existing Go-stdlib-only CVEs (toolchain-level, continue-on-error in CI) — unrelated to this diff.
  • make test-cover-gate's full-parallel -race run non-deterministically times out a PTY/emulator-heavy package (internal/tui/terminal or internal/agent, depending on run) on this loaded local machine — this is the documented pre-existing flake in gotchas/ci-gates.md (macOS PTY/pipe-device contention under full-suite -race). Confirmed pre-existing and unrelated to this diff by reproducing it with these changes fully stashed out. Confirmed passing via the documented workaround: go test -p 1 -race -count=1 ./... (fully serialized) is green with full coverage — internal/tui 83.4%, internal/tui/hera 92.3%. Also broadened the existing ci-gates.md bullet to note the flake also hits internal/tui/terminal/internal/tui, not just internal/agent.
  • New/changed tests verified to fail against the old code (reverted the fix line locally, confirmed TestHandleSessionExitUI_RerenderRestartsWhenViewedViaHeraPane fails with status=in_review) and pass with the fix restored.

🤖 Generated with Claude Code

…l nav

The session wasn't misclassified as dead — it was genuinely stopped by a
legitimate size-drift kick (heraKickRerender, BUG-074), whose auto-restart
then unconditionally skipped itself. handleSessionExitUI's "is the user
still watching" gate checked only a.mode==modeAgent (the classic fullscreen
agent view), but the native Hera view never sets that mode — it stays
modeTaskList with ActiveTab()==TabHera regardless of which pane is focused.
So every kick fired from a Hera pane took the "user navigated away, settle
at InReview" branch, even while the operator was watching it live in Hera.

Fix: App.isViewingTaskSession recognizes both ways of "watching" — the
classic agent view, or the Hera tab with the task bound to either pane via
the new HeraPage.IsBoundToTask. handleSessionExitUI now uses it instead of
the inline modeAgent-only check.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/drn/argus/internal/tui 82.94% (+0.15%) 👍
github.com/drn/argus/internal/tui/hera 92.29% (+0.00%) 👍

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/drn/argus/internal/tui/app.go 77.70% (+0.54%) 2605 (+5) 2024 (+18) 581 (-13) 👍
github.com/drn/argus/internal/tui/hera/panes.go 94.35% (+0.05%) 124 (+1) 117 (+1) 7 👍

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/drn/argus/internal/tui/app_test.go
  • github.com/drn/argus/internal/tui/hera/panes_test.go
  • github.com/drn/argus/internal/tui/heraactions_test.go

@anutron
anutron merged commit fb8bc37 into master Aug 2, 2026
1 check passed
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.

1 participant