CPLAT-11459: daily/artifact-centric view (day → project → session) + startup stall fix - #155
Merged
Merged
Conversation
… stall fix Adds a daily view to the session browser: a day → project → session tree whose preview answers "what came out of this day?" rather than showing conversation text. `D` toggles it from the project browser; each view keeps its own preview mode, and the cursor follows across the swap. The preview is a "Produced (N)" digest — PRs, Jira issues, artifacts, plans. Enter jumps to the conversation turn where an output FIRST appeared, o opens it externally, y copies it. Duplicate outputs across sessions collapse into one row anchored to the session that produced it first. Startup: 2726ms → 227ms to first frame. NewApp was spending 2.46s inside cleanupStaleRemoteSessions(), which pings every saved remote synchronously — one unreachable SSH host cost the full ConnectTimeout before anything painted. It now runs as a command from Init(), concurrent with the scan. Separately, tmux.HasClaude read the whole `ps -e` table once per pane; one memoized process-tree snapshot replaces it (CurrentWindowClaudes 219ms → 106ms cold, 0s warm). Closes a design gap behind the jump: SessionRef recorded FirstSeen but not the uuid of the entry where a ref first appeared, so PR/Jira rows had no jump target. Adds FirstSeenUUID, populated in both extraction paths and carried through ResolveRef's cache merge — that cache is keyed by URL and shared process-wide, so without it the same PR seen in two sessions serves session B's uuid to session A. Gob compatibility with pre-upgrade caches is pinned by a test: loadCache returns an EMPTY cache on decode error, so a break would silently cost every user a full rescan. Correctness fixes found along the way: - panic: prompt[:maxW-3] crashed the render at narrow list widths (width 11) - CJK: project names and prompts were byte-sliced against a cell budget, cutting mid-rune; now runewidth-based - number keys 1-9 fired preview modes that cannot exist on a day row, and the hint line advertised all ten; suppressed for those rows only - cursor highlight was frozen on day-scoped project rows (re-render branch only handled day rows) - y copied nothing for path-only outputs (plan files) - a day's last project always drew ├─ (projectItem had no treeLast) - rebuild re-found aggregate rows via their newest session, so the live tick dropped the cursor into a child row on an active day - toggling into a folded destination stranded the cursor; the destination is now built fully expanded and only the target's own ancestors are unfolded JIRA: https://sendbird.atlassian.net/browse/CPLAT-11459
|
| Commit | Scanned at | New | Resolved | Net |
|---|---|---|---|---|
5f95382 < |
2026-08-13 14:33 UTC | 0 | 0 | 0 |
Last scanned: 5f95382 · 2026-08-13 14:33 UTC
|
| Commit | Scanned at | New | Resolved | Net |
|---|---|---|---|---|
5f95382 < |
2026-08-13 14:33 UTC | 0 | 0 | 0 |
Last scanned: 5f95382 · 2026-08-13 14:33 UTC
Kairo-Kim
approved these changes
Aug 13, 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-11459
Summary
Adds a daily / artifact-centric view to the session browser: a
day → project → sessiontree whose preview answers "what came out of this day?" rather than showing conversation text.Dtoggles it from the project browser; each view keeps its own preview mode, and the cursor follows across the swap.The existing browser answers "which sessions exist". It does not answer "what did I actually produce today" — the PRs, Jira issues, published artifacts, and plans a day's work left behind, with a path back to the conversation turn that produced each one.
What it does
day → project → session, each tier aggregating what it needs: output rollup badges on day rows, lifecycle + message counts on project rows.Enterjumps to the conversation turn where that output first appeared ·oopens it externally (URL → path) ·ycopies.Startup: 2726ms → 227ms to first frame
NewAppwas spending 2.46s incleanupStaleRemoteSessions(), which pings every saved remote session synchronously. One saved remote whose SSH host is unreachable costs the fullConnectTimeoutbefore ccx paints anything.It now runs as a command dispatched from
Init(). Batched commands run concurrently, so the sweep overlaps the session scan and costs nothing on screen; aremotesCleanedMsghandler drops the virtual row only when the remote actually vanished.NewAppSeparately,
tmux.HasClauderead the fullps -etable once per pane. One memoized process-tree snapshot (2s TTL) + BFS replaces it:CurrentWindowClaudesclaudesInWindowDesign gap closed: first-occurrence message UUID
session.SessionRefrecordedFirstSeen(a timestamp) but not the uuid of the entry where the ref first appeared — so a PR/Jira row had no jump target at all.Adds
SessionRef.FirstSeenUUID, populated in both extraction paths (the raw-line scanner via a newlineUUID(), andExtractSessionRefsviaentries[i].UUID) and carried throughResolveRef's cache merge at bothgetCachedRefsites.That last part matters: the resolve cache is keyed by URL and shared process-wide, so the same PR seen in two sessions would otherwise serve session B's uuid to session A. Reverting it fails with
got "sessionA-entry", want "sessionB-entry".Gob compatibility with pre-upgrade caches is pinned by a test — gob matches by field name, so an old
.ccx-cache.gobdecodes withFirstSeenUUID="". Worth pinning becauseloadCachereturns an empty cache on any decode error: a break would silently cost every user a full rescan.Correctness bugs fixed along the way
prompt[:maxW-3]→slice bounds out of range [:-1]at narrow list widths (reproduced at width 11), crashing the whole render1–9still fired preview-mode switches and the hint listed all ten. Suppressed for those rows only — plain project rows in the non-daily browser keep them, sinceselectedSession()falls back to a real session thereycopied nothing for path-only outputs (plan files), reporting "No URL for this output"├─—projectItemhad notreeLastfielddayKey,dayKey+path)VisibleItems()and fell through. The destination is now built fully expanded and the target's real ancestor chain is walked, so a new grouping mode gets this for free — and only those ancestors are unfolded, since fold state is persisted and a blanket expand would follow the user into the next launchTesting
gofmtandgo vetclean; full suite green with an isolatedHOME. Every regression test was verified by reverting its fix and confirming the test fails — e.g. the Enter jump fails withcursor landed on entry "u1", want the first mention u2, exactly the reported symptom.