Skip to content

Commit 707374d

Browse files
fix(stats): say why each adapter is Skipped
Skipped adapters all got the same 'no real chat activity' line, even when they had recorded events. Split them into two groups: adapters with zero events, and adapters with some activity that is below the real-usage threshold. Refs #1254
1 parent 4621364 commit 707374d

2 files changed

Lines changed: 30 additions & 7 deletions

File tree

‎src/session/analytics.ts‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2762,6 +2762,9 @@ function renderConversation(c: ConversationStats, conversationUsd: string, contr
27622762
* 2. Filtered adapters (`isReal=false` but with at least one .db on disk)
27632763
* become a single "Skipped (N): name1, name2, ..." disclosure line so
27642764
* the user sees that fixtures/probes were intentionally hidden.
2765+
* Below that line, adapters with zero events are listed under
2766+
* "No real chat activity", and adapters with some events are listed
2767+
* under "Some activity, but below the real-usage threshold".
27652768
*
27662769
* Returns [] when `multiAdapter` is undefined OR when there are no real
27672770
* adapters AND nothing skipped — keeping the renderer additive (Slice 3.5).
@@ -2806,9 +2809,17 @@ function renderMultiAdapter(multiAdapter: MultiAdapterLifetimeStats | undefined)
28062809
if (skipped.length > 0) {
28072810
if (real.length > 0) out.push("");
28082811
const names = skipped.map((a) => adapterLabel(a.name)).join(", ");
2812+
const empty = skipped.filter((a) => a.eventCount === 0);
2813+
const belowThreshold = skipped.filter((a) => a.eventCount > 0);
28092814
out.push(` Skipped (${skipped.length}): ${names}`);
2810-
out.push(" These adapters have DBs on disk but only test fixtures, dev skeletons,");
2811-
out.push(" or detection probes — no real chat activity.");
2815+
if (empty.length > 0) {
2816+
const emptyNames = empty.map((a) => adapterLabel(a.name)).join(", ");
2817+
out.push(` No real chat activity: ${emptyNames}`);
2818+
}
2819+
if (belowThreshold.length > 0) {
2820+
const belowNames = belowThreshold.map((a) => adapterLabel(a.name)).join(", ");
2821+
out.push(` Some activity, but below the real-usage threshold: ${belowNames}`);
2822+
}
28122823
}
28132824

28142825
return out;

‎tests/session/multi-adapter-render.test.ts‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
* JetBrains — 8.6 MB 8.6 MB
1717
*
1818
* Skipped (7): Cursor, Codex CLI, Pi, Kiro, Gemini CLI, Openclaw
19-
* These adapters have DBs on disk but only test fixtures, dev skeletons,
20-
* or detection probes — no real chat activity.
19+
* No real chat activity: Kiro, Gemini CLI, Openclaw
20+
* Some activity, but below the real-usage threshold: Cursor, Codex CLI, Pi
2121
*
2222
* Slice 3.5 backward compat is asserted indirectly: this file passes the
2323
* `multiAdapter` opt and asserts new behaviour. The pre-existing
@@ -159,14 +159,14 @@ describe("Slice 3.2 — formatReport renders 'Where it came from' sub-block", ()
159159
});
160160

161161
describe("Slice 3.3 — Skipped adapters disclosure", () => {
162-
test("lists skipped adapter names with count and 'no real chat activity' rationale", () => {
162+
test("lists skipped adapter names with count and a separate rationale per group", () => {
163163
const text = formatReport(baseReport(), "1.0.111", null, {
164164
lifetime: lifetime(),
165165
multiAdapter: multi([
166166
adapter("claude-code", { events: 17_413, data: 276_700_000, projects: new Array(12).fill(0).map((_, i) => `/p/${i}`), isReal: true }),
167167
adapter("cursor", { events: 5, data: 100, projects: ["/p/c"], isReal: false }),
168168
adapter("codex", { events: 2, data: 50, projects: ["/p/cdx"], isReal: false }),
169-
adapter("pi", { events: 1, data: 20, projects: ["/p/pi"], isReal: false }),
169+
adapter("pi", { events: 0, data: 0, projects: ["/p/pi"], isReal: false }),
170170
]),
171171
});
172172
expect(text).toMatch(/Skipped \(3\):/);
@@ -175,8 +175,20 @@ describe("Slice 3.3 — Skipped adapters disclosure", () => {
175175
expect(text).toMatch(/Codex/);
176176
expect(text).toMatch(/Pi/);
177177
// Disclosure rationale.
178-
expect(text).toMatch(/no real chat activity/i);
178+
expect(text).toMatch(/ No real chat activity: Pi/);
179+
expect(text).toMatch(/below the real-usage threshold: Cursor, Codex CLI/);
179180
});
181+
test("skipped adapter with some events is not described as 'no real chat activity'", () => {
182+
const text = formatReport(baseReport(), "1.0.111", null, {
183+
lifetime: lifetime(),
184+
multiAdapter: multi([
185+
adapter("claude-code", { events: 17_413, data: 276_700_000, projects: new Array(12).fill(0).map((_, i) => `/p/${i}`), isReal: true }),
186+
adapter("cursor", { events: 40, data: 100, projects: ["/p/c"], isReal: false }),
187+
]),
188+
});
189+
expect(text).not.toMatch(/no real chat activity/i);
190+
expect(text).toMatch('below the real-usage threshold');
191+
})
180192

181193
test("when no adapters are skipped, no 'Skipped' line appears", () => {
182194
const text = formatReport(baseReport(), "1.0.111", null, {

0 commit comments

Comments
 (0)