Skip to content

Stop the tree flickering on zombie intermediate parents; skip dead sessions in parent auto-detect - #4

Draft
curusarn wants to merge 1 commit into
mainfrom
fix-zombie-parent-tree-flicker
Draft

Stop the tree flickering on zombie intermediate parents; skip dead sessions in parent auto-detect#4
curusarn wants to merge 1 commit into
mainfrom
fix-zombie-parent-tree-flicker

Conversation

@curusarn

Copy link
Copy Markdown
Owner

Problem

When an intermediate parent in the session hierarchy is a zombie (killed session that live sessions still reference as parent, e.g. crab-t-10026-worker referenced by crab-u7449-conflict), the TUI session list flickered between two shapes:

Shape A (correct) — dead parent as a dimmed virtual root:

>        t-10026-worker                       -   -
  local  ├── crabctl-zombie-parent  running
  local  └── u7449-conflict         waiting
  local  orchestrator               waiting

Shape B (glitched, ~1.5s after every remote poll) — the zombie re-nests under its own recorded parent, children pushed a level deeper, roots reorder:

  local  orchestrator                             waiting
>        ├── t-10026-worker                       -   -
  local  │   ├── crabctl-zombie-parent  running
  local  │   └── u7449-conflict         waiting

Root causes

  1. Flicker: the remoteSessionsMsg handler (and the ctrl+h fold path) re-feed BuildTree its own previous output, which contains the synthetic Virtual row for the dead parent. Inside BuildTree that stale row registered as an active session, so it stopped being a virtual root, picked up its own DB parent, and re-nested its subtree. The next local refresh dropped it again — flicker on alternating refreshes. Fix: BuildTree drops Virtual rows from its input (they are derived placeholders, always re-created).

  2. Zombie edges keep being created: DetectParent trusted CRABCTL_NAME (which outlives the tmux session it came from) with no liveness check, so spawns recorded parents that had been dead for an hour. Fix: all auto-detect call sites (crabctl new, TUI /new, dir-picker, orchestrator spawn) reroute a dead detected parent to its nearest live ancestor via the recorded parent chain (top level if the whole chain is dead, cycle-safe). Explicit -p is still trusted as-is.

Tests

  • TestBuildTreeZombieIntermediateParent — A live ← B dead ← C live: B renders as virtual root, C nested, no rows lost
  • TestBuildTreeRebuildFromOutputStable — the regression: rebuilding from previous output is shape-stable (failed before the fix with exactly the depth shifts seen live)
  • TestBuildTreeWholeChainDead — only the direct dead parent materializes
  • TestNearestLiveAncestor — live candidate, dead→live walk, all-dead chain, cycle safety, unknown candidate

go test ./... and go vet ./... green.

Verification against the live tmux server

  • Before: flicker to shape B captured within 40s of watching.
  • After: 10 frames over 60s, shape stable; virtual root never re-nests.
  • Facet 2: CRABCTL_NAME=crab-t-10026-worker crabctl new zzz-test-child (stale env pointing at the dead session) resolved Parent: crab-orchestrator — the nearest live ancestor.

🤖 Generated with Claude Code

…p auto-detecting dead parents

Two fixes for zombie (killed) sessions that live sessions still reference
as parent:

1. BuildTree now drops Virtual rows from its input. The TUI re-feeds
   BuildTree its own output (remote-session merges, ctrl+h fold rebuilds),
   and a stale virtual row registered as an active session: the dead parent
   stopped being virtual, picked up its own recorded parent from the DB,
   and its whole subtree re-nested one level deeper — so the list flickered
   between two shapes on alternating local/remote refreshes.

2. Parent auto-detection (crabctl new, TUI spawn flows) now checks that the
   detected parent actually has a live tmux session. CRABCTL_NAME env
   outlives the session it came from, so spawns kept recording edges to
   long-dead sessions. A dead candidate is rerouted to its nearest live
   ancestor via the recorded parent chain (top level if the chain is dead).
   Explicit -p is still trusted as-is.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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