diff --git a/scripts/quality-gate-local.sh b/scripts/quality-gate-local.sh index 6624ddc..f3f657a 100755 --- a/scripts/quality-gate-local.sh +++ b/scripts/quality-gate-local.sh @@ -45,6 +45,16 @@ calc_cpu_stats() { mkdir -p "$(dirname "$BENCH_FILE")" : > "$BENCH_FILE" +# The bench file is a synthetic transcript inside the real corpus; without +# cleanup it shows up in the UI as a project full of "quality gate payload" +# messages. Remove it (and its directory, if the gate owns it) on every exit +# so the watcher drops the conversation again. +cleanup_bench() { + rm -f "$BENCH_FILE" + rmdir "$(dirname "$BENCH_FILE")" 2>/dev/null || true +} +trap cleanup_bench EXIT + log "Building and starting container" docker compose up -d --build chat-explorer >/dev/null sleep 6 diff --git a/src/analytics-web/chats_mobile.html b/src/analytics-web/chats_mobile.html index d9623e8..af779dc 100644 --- a/src/analytics-web/chats_mobile.html +++ b/src/analytics-web/chats_mobile.html @@ -482,6 +482,30 @@ margin-right: 6px; } + /* Session-source badges (headless / desktop / worktree agent). + Interactive CLI sessions carry no badge. */ + .source-badge { + font-size: 10px; + font-weight: 600; + letter-spacing: 0.4px; + text-transform: uppercase; + padding: 2px 6px; + border-radius: 4px; + margin-right: 6px; + } + .source-badge.source-headless { + color: #b48ede; + background: rgba(140, 82, 200, 0.15); + } + .source-badge.source-desktop { + color: #6db3d6; + background: rgba(70, 140, 180, 0.15); + } + .source-badge.source-worktree { + color: #d6a86d; + background: rgba(180, 130, 60, 0.15); + } + /* Subagent count badge */ .subagent-count { font-size: 11px; @@ -1193,6 +1217,63 @@ padding-left: 36px; } + /* "Automated runs" cluster: headless SDK sessions outnumber + interactive ones inside a project folder, so they collapse behind a + sub-header. Deliberately quieter than .project-header - no avatar, no + sticky positioning, muted text - so it reads as a divider inside the + group rather than a second group. */ + .cluster-header { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 20px 8px 36px; + background: var(--bg-primary); + border-bottom: 1px solid var(--border-primary); + cursor: pointer; + transition: background-color 0.2s ease; + } + + .cluster-header:hover { + background: var(--bg-secondary); + } + + .cluster-label { + color: var(--text-secondary); + font-size: 0.8rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + } + + .cluster-count { + color: var(--text-secondary); + background: var(--bg-tertiary); + font-size: 0.75rem; + font-weight: 500; + padding: 1px 8px; + border-radius: 10px; + } + + .cluster-toggle { + margin-left: auto; + color: var(--text-secondary); + display: flex; + align-items: center; + } + + .cluster-toggle-icon { + transition: transform 0.2s ease; + } + + .cluster-toggle-icon.expanded { + transform: rotate(180deg); + } + + /* Cluster members sit one level deeper than their sub-header. */ + .project-group .conversation-item.automated-item { + padding-left: 52px; + } + .conversation-state { font-size: 0.7rem; padding: 3px 8px; @@ -2782,6 +2863,23 @@