Skip to content

CPLAT-9497: overhaul artifact browser split rendering and page navigation#23

Merged
gavin-jeong merged 82 commits intomasterfrom
CPLAT-9497-entity-tree-cron-support
Apr 17, 2026
Merged

CPLAT-9497: overhaul artifact browser split rendering and page navigation#23
gavin-jeong merged 82 commits intomasterfrom
CPLAT-9497-entity-tree-cron-support

Conversation

@gavin-jeong
Copy link
Copy Markdown
Collaborator

JIRA: https://sendbird.atlassian.net/browse/CPLAT-9497


Summary

  • Fix split divider alignment using ANSI CHA cursor positioning with full space padding for bubbletea compatibility — resolves persistent misalignment with CJK/ambiguous-width characters
  • Add left/right focus toggle for browser pages with scrollable right-pane viewport
  • Consume all keys in browser mode to prevent leak-through to conversation handler
  • Files page shows only Write/Edit files (not Read context), filters out images
  • Remove overview page, x-prefixed actions (xo/xe/xy), g/G/pgup/pgdn nav, [/] resize
  • Fix test env managed settings prompt (copy remote-settings.json, inject trust with symlink resolution)
  • Add comprehensive split divider alignment tests

Test plan

  • Open conversation, press p to browse pages (URLs, Images, Changes, Files)
  • Verify divider stays aligned during resize and with Korean/CJK content
  • Press l/right to focus right pane, scroll with j/k/pgup/pgdn
  • Press h/left/esc to return to list
  • Verify [/] resize works in all browser pages
  • Files page shows only modified files, not Read context
  • xo/xe/xy actions work in each page
  • Config test launcher skips managed settings prompt

Security checklist (Infrastructure code)

  • I have checked below conditions:
    • This PR doesn't contain any SecurityGroup rule changes which are not allowed via INF Jira ticket
    • This PR doesn't contain any public open SecurityGroup inbound rules(0.0.0.0/0) except the predefined service port
    • This PR doesn't contain any resources in a public subnet except those are needed with a specific technical reason
    • This PR doesn't contain any credentials (AWS Secret key, password, API tokens, etc)
    • This PR doesn't contain any IAM users which are not allowed via UAC Jira approval
    • The contents of this PR is following the guide from OSWAP and SendBird Secure Software Development Lifecycle

Entity Tree View:
- Toggle left pane between flat conversation list and entity tree
  (tab when left-focused, or :tree command)
- Right pane detail level cycles independently (tab when right-focused)
- Tree shows Agents, Background Jobs, and Task Board sections
- Compact labels: Agent: shortID [type], BG: id command, Task: #id subject
- Rich preview: agents show full subagent conversation with tool calls,
  bg jobs show actual command output, tasks show full activity span
- J key jumps from conv sub-item to matching entity in tree
- ConvKeymap with configurable JumpToTree key

Agent Navigation Fixes:
- Parse toolUseResult.agentId from session JSONL (was reading empty
  top-level field)
- Build toolUseToAgent map for direct agent ID lookup instead of
  timestamp heuristics
- Fix bg task navigation: match actual TaskOutput result instead of
  "Command running in background" acknowledgement
- TaskCreate operations now visible as sub-items (task detection
  decoupled from task list existence)

Configurable Refresh:
- All views use keymap.Session.Refresh instead of hardcoded "R"
- Added refresh to Stats and Hooks views (previously had none)
- Help lines use configurable key
URLs ending with `**` (markdown bold markers) were stored as-is,
producing invalid URLs in the picker. Add `*` to the TrimRight
character set alongside existing punctuation.
Add cron-aware session scanning and TUI views so cron jobs can be filtered, inspected, and drilled into alongside tasks, agents, and background jobs.
Stop the sessions view from reapplying a cleared filter during live refresh by clearing the stored startup search query when esc resets the active filter.
Roll up project stats by base repo so worktrees aggregate together, and show each repo's cost ratio in the stats detail view.
Update the top-level stats project summary renderer to display the rolled-up repo path so worktree paths no longer appear in the stats view.
Keep the rolled-up repo stats detail and add a separate project-path breakdown so both repo and project perspectives are available.
Add CLI picker support and TUI navigation updates for session stats, repo aggregation, URL/file actions, and conversation live-tail behavior so browsing active work is easier without losing manual context.
Add a conversation subcommand with multi-line rows, turn-scoped artifact previews, and picker interactions for opening, editing, and jumping to related conversation turns.
Bring master into the feature branch, keep the current session picker, repo stats, live-tail, and conversation picker changes, and resolve the PR merge conflicts.
Multi-line conversation rows could overflow the list height, clipping
the first item. Switch from pre-computed visMax to real-time line
counting so items always render within the available space.
Indent multi-line conversation body rows to the same text column as the
header, rather than the far-left gutter, so wrapped lines align cleanly
under the selected item's header text.
Keep assistant turns with failed tool results visible in conversation views
and show an explicit error summary in previews so verbose mode exposes
Bash/tool_result failures instead of collapsing them into tool-only turns.
Add tab-based mode cycling to ccx conversation and change standard
conversation preview in the main TUI to show text plus artifact summaries
instead of raw tool blocks.
Insert divider lines between merged preview turns so compact and standard
conversation previews are easier to scan when multiple turns are shown
in a single preview entry.
Switch picker truncation and padding from byte-length checks to terminal
display width so CJK and other wide glyphs align correctly in the
conversation picker.
Standard conversation preview renders directly from the raw entry, so it
was bypassing the turn separators added to synthetic preview entries.
Insert separators when multiple embedded turn headers are present so the
preview is easier to scan.
Compact and standard previews were flattening all text blocks together,
which removed the boundaries needed for visible separators. Render text
by block chunks so divider lines actually appear between turns.
When the conversation preview is focused, show a left-side tooltip for the
focused artifact block. Reuse existing diff rendering for change blocks and
show concise details for files, URLs, and images.
Replace aggregate artifact counts in standard conversation preview with
per-artifact preview blocks so the existing block cursor can navigate
and select concrete files, URLs, images, and changes.
Drop the old count-based standard preview renderer so conversation
STANDARD uses only the synthesized artifact-row path and tests reflect
the active behavior.
Render per-turn artifacts in standard conversation preview as a passive
list instead of selectable-looking rows, while keeping the left-side
detail tooltip for focused artifact context.
Make the focused artifact tooltip image-aware using cache-only lookup for
passive preview. Show an image detail card with paste ID and cached path
when available, while keeping explicit open behavior unchanged.
Add a new internal/kitty package for terminal capability detection and
Kitty graphics protocol image drawing. When a focused image artifact has
a cached file and the terminal supports Kitty graphics, draw the image
inline over the tooltip area. Falls back to the existing text card in
unsupported terminals.
Add CCX_KITTY=1 env override and KITTY_WINDOW_ID/KITTY_PID fallback
detection for tmux sessions where TERM_PROGRAM is lost. Wrap Kitty
graphics escape sequences in tmux DCS passthrough so they reach the
outer terminal correctly.
Place inline images at the tooltip's computed position instead of a fixed
corner, and emit a clear command on every non-image frame so stale images
disappear when focus moves away.
Query tmux server environment for TERM_PROGRAM and KITTY_WINDOW_ID so
Kitty graphics support is detected automatically without requiring
CCX_KITTY=1 when running inside tmux on a Kitty-compatible terminal.
Position the inline image inside the tooltip box area using the same
cursor-relative Y calculation as overlayTooltip, accounting for the
text header lines. The clear command on every non-image frame already
handles resize and defocus cleanup.
Emit a Kitty graphics clear command after the TUI exits so inline images
do not persist in the terminal after ccx terminates.
Tighten the artifact page actions hint and reformat the shared item
context renderer so timestamp, turn preview, and related user prompt are
presented in clearer sections across all artifact pages.
Remove dead text-board helpers, keep the split-browser path as the only
conversation page implementation, and align tests with the real page
openers/state. Stabilize the browser around enriched page items and a
read-only right detail pane.
Finish the conversation artifact pages as a left-list/right-detail browser
with page-aware actions, richer item context, and consistent help text.
Keep the normal conversation view unchanged while letting `p` pages serve
as focused artifact browsers.
Route the artifact page actions menu through shared page-aware helpers so
URLs, files, changes, and images all use one coherent open/edit/copy
flow backed by the richer convPageItem model.
Avoid reloading and rebuilding agent preview content in updateConvPreview
when the selected agent item already matches the current preview cache.
This keeps agent navigation cheaper without changing behavior.
Replace duplicated tab-driven pane/detail mode switching in
handleConversationKeys with the existing setConvLeftPaneMode and
setConvDetailLevel helpers so the behavior stays centralized and
consistent.
Make artifact browser list truncation width-aware and align the page
action hints with the actual supported image actions so the browser
finishes with a more coherent UX.
Ignore local .claude workspace files so the branch stays clean while
working with plans, scheduled tasks, and local settings.
Introduce an explicit overview page for the conversation artifact browser
so `p` works consistently while already inside a page, `overview` becomes
a real destination, and browser help text reflects page mode and resize
behavior.
Remove the pseudo none page and use overview as the explicit default for
the conversation artifact browser. This simplifies page state checks and
makes the browser model more coherent.
Remove the stale convPageNone check from App.View() so the explicit
overview page actually renders as the default artifact browser page.
This aligns the page model with the earlier overview-state refactor.
Separate browser activation from page selection so the normal
conversation split remains intact unless the user explicitly enters the
artifact browser via `p`.
Pressing `p` in the normal conversation view now only opens the page
menu. The artifact browser activates only after selecting a page,
preventing the blank browser shell from replacing the normal preview.
Clear conversation page browser state on each fresh conversation open so
normal conversation view is restored and stale browser activation does
not leak across sessions.
When `p` opens the conversation page picker, render the menu overlay
without immediately replacing the conversation body with the artifact
browser. The browser now renders only after the page menu closes.
Use a narrower default split ratio for the artifact browser so the right
detail pane has more space, and clamp the left breadcrumb text before
appending right-aligned status so long detail content no longer appears
to eat the header.
- Fix split divider alignment using ANSI CHA cursor positioning with
  full left+right space padding for bubbletea compatibility
- Add left/right focus toggle for browser pages with scrollable
  right-pane viewport for long content
- Consume all keys in browser mode to prevent leak-through to
  conversation split handler
- Files page shows only modified files (Write/Edit), not Read context
- Filter image files from Files page (belong in Images page)
- Remove overview page concept, make URLs the default page
- Use x-prefixed actions (xo/xe/xy) instead of direct enter/e/y
- Add g/G/pgup/pgdn navigation in browser list
- Add [/] resize support in browser pages
- Fix test env managed settings prompt by copying remote-settings.json
  and injecting project trust with symlink-resolved paths
- Add comprehensive split divider alignment tests (ASCII, Korean,
  ambiguous-width, styled, overflow, resize, empty)
Add 30ms debounce to preview rendering across all split-pane views
(conversation, sessions, config, plugins). Rapid j/k scrolling now
skips intermediate expensive renders (fold re-rendering, file I/O,
text wrapping) and only updates when the user pauses.
The browser list now scrolls to keep the cursor visible when items
exceed the available height, with ↑/↓ indicators showing overflow.
Replace lipgloss.Render for the border cell with direct ANSI 24-bit
color sequence to prevent style wrapping artifacts that caused
double-colored lines at the split divider.
Reserve rows for ↑/↓ indicators before computing the window range
so the cursor never falls outside the visible item range.
Press i to show/hide the kitty-rendered image preview in the
artifact browser's Images page. Defaults to on, help line shows
current state.
Copy link
Copy Markdown

@jinsekim jinsekim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

- Right pane now shows metadata (timestamp, turn, user prompt) above
  the content separator, with page-specific detail below
- Left list shows a thin separator line between items from different
  user prompts so related items are visually grouped
- Actions menu shows o/e/y instead of xo/xe/xy since x was already
  pressed to open the menu
Press / to open a live search filter in any browser page (URLs,
Images, Changes, Files). Matches against label, URL, and user
prompt. First esc clears the filter, second esc closes the browser.
Active filter shown as a badge in the help line.
`ccx sessions` outputs tab-separated session metadata sorted by
most recent first: ID, ShortID, ModTime, MsgCount, Project, Prompt.
Uses cached sessions with fallback to full scan.
Default behavior now lists only sessions matching the current tmux
window's project paths. Use --all to list every session.
Filter to live sessions in the current tmux window instead of all
historical sessions for the project. Use --all for the full list.
@gavin-jeong gavin-jeong merged commit 6e2d944 into master Apr 17, 2026
3 checks 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.

2 participants