CPLAT-9497: preserve conv preview selection + fix LIVE/HERE markers#38
Merged
Merged
Conversation
JIRA: https://sendbird.atlassian.net/browse/CPLAT-9497 Conversation preview was losing user state across detail-mode switches and surfacing the wrong content for tasks built from TaskCreate-only tool calls. This rework unifies the preview pipeline behind a single abstraction so the three modes apply consistently and the user's position survives mode toggles and parent-pane drilldowns. Selection preservation across compact / standard / verbose: - Introduce previewBuild { Header, Sources, Fallback } and three uniform transformers (compactPreview / standardPreview / verbosePreview). All preview kinds — convMsg, convTask, convAgent, convBgJob — emit one of these, so per-kind branching downstream is gone. - Track per-block source-entry index on FoldState.BlockSourceIdx; the anchor capture/restore now matches by sourceIdx first (with tool-name ordinal + preview-core-text + raw-text fallbacks), so a selected block keeps its position when switching modes. - Tree-mode task / agent / bg-job previews now honour the right-pane detail level, matching the flat conversation view. Verbose retains the rich synthetic entry. Tasks built from TaskCreate-only tool inputs were missing a task.ID, causing extractTaskEntries to fall back to subject-less JSON matching and surface unrelated entries. Resolve the ID against the session task list at buildConvItems time; when no ID can be found, the Enter handler opens the parent message in msgFull instead of drilling into the wrong task. Drilldown ESC behaviour: - popNavFrame now restores leftPaneMode + treeItems via rebuildConversationList, so the cursor lands on the correct slice regardless of flat/tree mode. - ESC in a drilldown pops to the parent and re-opens the preview so a second ESC closes that preview cleanly, never skipping past the parent into the session list. ESC in plain conv view with the preview already closed is now a no-op — use 'left' for the explicit session-list exit. Tests: - TestModeCyclePreservesOriginalSelection covers compact ↔ standard ↔ verbose round-trips with a deliberately mis-aligned source layout. - TestStandardToVerbosePreservesToolOnlyTurn covers the "[[TaskUpdate]]" summary -> tool_use mapping. - TestVerboseToolToCompactFallsBackToPrecedingText covers the tool/result -> nearest plain-text fallback. - TestTreeTaskCompactModeFiltersToTextOnly + TestTreeBgJobPreviewShowsCommandAndOutput cover tree-mode mode transforms. - TestPopNavFrameRestoresParentConvPosition, TestEscFromTaskDrilldownReturnsToParentConv, TestEscClosesPreview cover the ESC navigation rules.
JIRA: https://sendbird.atlassian.net/browse/CPLAT-9497 Sessions sharing a project path with the user's active claude were spuriously marked LIVE and HERE in the session list. Two causes: 1. Claude processes wrapped by ccproxy (or any non-pane intermediary) have their parent PID pointing at the wrapper, not the tmux pane shell, so the previous direct-PPID classification dropped them into the orphan bucket. The orphan path then attributed them to the current window by cwd alone, which collided whenever another tmux window had a claude running in the same directory. 2. orphan claudes whose cwd happened to match a path in the current tmux window inherited the [HERE] badge even though they belonged to another window entirely. Fix: - classifyClaudeProcsByAncestry walks the PPID chain (via a ps -e -o pid=,ppid= snapshot) past wrappers like ccproxy / sudo / tee, attributing each claude to the first tmux pane shell it reaches. Subagents — claudes whose chain crosses another claude before any pane — are dropped entirely so the most-recent-session fallback can't promote unrelated past sessions. - True orphans (chain ends at init without ever hitting a pane) keep their LIVE marking via cwd but no longer auto-inherit HERE just because their cwd matches a current-window pane. - IsCurrentWindow is now reset alongside IsLive/IsResponding before re-running MarkLiveSessions on refresh, so HERE doesn't leak across refresh cycles after pane closes. Tests in internal/tmux/classify_test.go cover: - direct pane child + standalone orphan classification - single-level and nested subagent drop - ccproxy-wrapped claude attribution via ancestry walk - subagent under wrapped claude - corrupt-cycle defence - the user-reported rehome scenario (1 wrapped claude + 2 leftover orphans on the same cwd) marks only the wrapped one as direct
Kairo-Kim
approved these changes
May 12, 2026
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.
JIRA: https://sendbird.atlassian.net/browse/CPLAT-9497
Summary
previewBuildabstraction with per-block source-entry tracking, so the selected block (or its nearest text equivalent) survives mode toggles and parent-pane drilldown pops in both flat and tree views. Tree-mode task/agent/bg-job previews now honour the right-pane detail level. TaskCreate-only convTask items get theirtask.IDresolved against the session task list, so previews/enter-drilldowns target the right entries instead of accidentally landing on an unrelated TaskCreate burst.←remains the explicit exit.classifyClaudeProcsByAncestrywalks the PPID chain past wrappers, attributing each claude to its true owning pane shell. True orphans keep LIVE via cwd but no longer auto-inherit [HERE]. Subagents (claude under another claude) are dropped from the attribution pool.IsCurrentWindowis now reset alongside IsLive on refresh.Test plan
go test ./...— all greenTestModeCyclePreservesOriginalSelection— compact ↔ standard ↔ verbose round-trip selectionTestStandardToVerbosePreservesToolOnlyTurn— `[[TaskUpdate]]` summary → tool_use mappingTestVerboseToolToCompactFallsBackToPrecedingText— tool/result → nearest plain-text fallbackTestTreeTaskCompactModeFiltersToTextOnly+TestTreeBgJobPreviewShowsCommandAndOutput— tree-mode mode transformsTestPopNavFrameRestoresParentConvPosition,TestEscFromTaskDrilldownReturnsToParentConv,TestEscClosesPreview— ESC navigation rulesTestClassifyClaudeProcsByAncestry_*(5 cases including the user-reported rehome scenario) + nested subagent / cycle defence