fix: hierarchy drag crash, persistence loss, stale layout tabs - #123
Merged
Conversation
nox-0x
approved these changes
Apr 11, 2026
nox-0x
left a comment
Collaborator
There was a problem hiding this comment.
Solid fixes. Hierarchy drag isolation is clean, the merge logic in persistSession correctly handles undefined fields, and pruneStaleSessionTabs correctly handles all edge cases (empty prune, single-side prune, activeTabIndex clamping). Good defensive work.
aterrylu
marked this pull request as ready for review
April 11, 2026 06:17
Three related fixes for the sidebar hierarchy and layout persistence: 1. **Drag crash in hierarchy mode** — hierarchy drag handlers were calling startDrag() which activated the layout DropZoneOverlay. When dropping across tree levels, the overlay tried to split/move panes and crashed. Fix: hierarchy drag is sidebar-only reordering, no longer triggers layout DragContext. 2. **Manager/hierarchy persistence loss** — persistSession() did full-entry replacement, losing manager/template/project when called without those fields (e.g. during resume). Fix: merge fields with ?? fallback to preserve existing values for optional metadata. 3. **Stale layout tabs** — killed/exited sessions left ghost tabs in the persisted layout tree. The X button on the last ghost tab was a no-op (removeLeaf returns null for root). Fix: pruneStaleSessionTabs() runs after every fetchSessions poll, removing tabs for dead sessions and collapsing empty leaves. Also runs on unchanged session lists to clean up stale localStorage on page load. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests cover: single leaf (valid/stale/mixed tabs, activeTabIndex clamping), non-session tabs (orgchart/templates/preview never pruned), branch trees (collapse when children stale, deep nesting), referential equality preservation, and edge cases (empty leaf, extra valid IDs). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
aterrylu
force-pushed
the
terry/hierarchy-bugs
branch
from
April 11, 2026 06:18
f54b24a to
d4aac84
Compare
nox-0x
approved these changes
Apr 11, 2026
nox-0x
left a comment
Collaborator
There was a problem hiding this comment.
Clean, well-scoped fix for three distinct bugs. pruneStaleSessionTabs is correct (referential equality shortcut is sound, activeTabIndex clamping is right, null-collapse propagates correctly up the tree), persistSession merge with ?? is the right fix for undefined clobbering, and Sidebar drag isolation is the correct fix for the DropZoneOverlay crash. Comprehensive test coverage. LGTM.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes three related bugs in the sidebar hierarchy and layout persistence:
persistSession()did full-entry replacement, silently losingmanager/template/projectfields on resume. Now merges with??fallback.pruneStaleSessionTabs()cleans them up on every poll, including on fresh page load from localStorage.Changes
Sidebar.tsxstartDrag()/endDrag()from hierarchy drag handlers; add minimalsetDatafor browser compatlayoutTree.tspruneStaleSessionTabs()— recursive tree walker that removes dead session tabsstore.tspruneStaleSessionTabsafterfetchSessions; reset groups on full prune; run prune even when session list unchangedpersisted.tspersistSession()instead of full replace; guardstatus/manager/template/projectwith??Test plan
make check— lint, typecheck, 70 tests pass🤖 Generated with Claude Code