hacklab 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +33 -25
  2. package/dist/cli.js +1 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/config.d.ts.map +1 -1
  5. package/dist/commands/config.js +18 -19
  6. package/dist/commands/config.js.map +1 -1
  7. package/dist/commands/scan.d.ts.map +1 -1
  8. package/dist/commands/scan.js +5 -2
  9. package/dist/commands/scan.js.map +1 -1
  10. package/dist/commands/setup.d.ts.map +1 -1
  11. package/dist/commands/setup.js +32 -26
  12. package/dist/commands/setup.js.map +1 -1
  13. package/dist/commands/sync.d.ts.map +1 -1
  14. package/dist/commands/sync.js +32 -17
  15. package/dist/commands/sync.js.map +1 -1
  16. package/dist/config.d.ts +8 -2
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +1 -1
  19. package/dist/config.js.map +1 -1
  20. package/dist/prompt-consent.d.ts +37 -23
  21. package/dist/prompt-consent.d.ts.map +1 -1
  22. package/dist/prompt-consent.js +75 -58
  23. package/dist/prompt-consent.js.map +1 -1
  24. package/dist/prompt-stats.d.ts +116 -7
  25. package/dist/prompt-stats.d.ts.map +1 -1
  26. package/dist/prompt-stats.js +205 -25
  27. package/dist/prompt-stats.js.map +1 -1
  28. package/dist/scanners/incremental.d.ts +114 -17
  29. package/dist/scanners/incremental.d.ts.map +1 -1
  30. package/dist/scanners/incremental.js +235 -74
  31. package/dist/scanners/incremental.js.map +1 -1
  32. package/dist/scanners/index.d.ts +7 -3
  33. package/dist/scanners/index.d.ts.map +1 -1
  34. package/dist/scanners/index.js +8 -40
  35. package/dist/scanners/index.js.map +1 -1
  36. package/dist/scanners/util.d.ts +32 -15
  37. package/dist/scanners/util.d.ts.map +1 -1
  38. package/dist/scanners/util.js +10 -34
  39. package/dist/scanners/util.js.map +1 -1
  40. package/dist/sync.d.ts +3 -3
  41. package/dist/sync.d.ts.map +1 -1
  42. package/dist/sync.js +27 -14
  43. package/dist/sync.js.map +1 -1
  44. package/package.json +1 -1
@@ -1,8 +1,10 @@
1
1
  /** Buckets are `1..bucketMax`, so the axis stays readable at any prompt length. */
2
2
  export declare const PROMPT_LENGTH_BUCKET_MIN = 10;
3
3
  export declare const PROMPT_LENGTH_BUCKET_MAX = 100;
4
- /** The percentile that sets `bucketMax`; everything above lands in the overflow. */
5
- export declare const PROMPT_LENGTH_OVERFLOW_PERCENTILE = 0.9;
4
+ /** The percentile that sets `bucketMax`; everything above it lands in `tail`. */
5
+ export declare const PROMPT_LENGTH_AXIS_PERCENTILE = 0.9;
6
+ /** The server's cap on `tail` entries; longer distributions are coarsened. */
7
+ export declare const PROMPT_TAIL_MAX_ENTRIES = 400;
6
8
  /** Matches the backend's cap — anything longer is truncated before upload. */
7
9
  export declare const CONVERSATION_SAMPLE_MAX_CHARS = 20000;
8
10
  export type PromptStatsProject = {
@@ -10,6 +12,27 @@ export type PromptStatsProject = {
10
12
  promptCount: number;
11
13
  lastActiveAt: string;
12
14
  };
15
+ /** One session's running aggregate, as both the tick and a full scan build it. */
16
+ export type PromptSessionAggregate = {
17
+ /** ISO timestamp of the first prompt seen in this session. */
18
+ startedAt: string;
19
+ /** ISO timestamp of the most recent one. */
20
+ lastActiveAt: string;
21
+ promptCount: number;
22
+ };
23
+ /** One day's running tally. Cumulative for this machine, never a delta. */
24
+ export type PromptDayAggregate = {
25
+ prompts: number;
26
+ words: number;
27
+ };
28
+ /**
29
+ * The whole prompt-activity aggregate, keyed for cheap merging: sessions by
30
+ * session id, days by YYYY-MM-DD.
31
+ */
32
+ export type PromptActivityAggregate = {
33
+ sessions: Record<string, PromptSessionAggregate>;
34
+ daily: Record<string, PromptDayAggregate>;
35
+ };
13
36
  export type PromptStats = {
14
37
  totalPrompts: number;
15
38
  bucketMax: number;
@@ -17,7 +40,27 @@ export type PromptStats = {
17
40
  length: number;
18
41
  count: number;
19
42
  }[];
43
+ /**
44
+ * The exact distribution above `bucketMax`, and the only place those prompts
45
+ * are reported — the histogram stops at `bucketMax`. One entry per distinct
46
+ * word count, ascending, coarsened if there are more than
47
+ * `PROMPT_TAIL_MAX_ENTRIES` of them. Always present, empty when nothing
48
+ * exceeds `bucketMax`: the field's presence is what tells the server this
49
+ * histogram is exact, as opposed to a legacy snapshot whose last bar lumped
50
+ * everything at or above `bucketMax`.
51
+ */
52
+ tail: {
53
+ length: number;
54
+ count: number;
55
+ }[];
20
56
  projects: PromptStatsProject[];
57
+ /**
58
+ * Sessions and per-day counts for the whole local history. Not part of the
59
+ * `promptStats` block on the wire — the caller hands it to `stageFullScan`,
60
+ * which re-bases the tick's incremental state on it and works out which rows
61
+ * this upload still has to carry.
62
+ */
63
+ activity: PromptActivityAggregate;
21
64
  /** Only ever set under the `full` consent tier. */
22
65
  conversationSample?: string;
23
66
  };
@@ -34,9 +77,43 @@ export type PromptStats = {
34
77
  export declare function promptTextFrom(entry: unknown): string | null;
35
78
  /** Whitespace-separated word count. Zero-word prompts are dropped by callers. */
36
79
  export declare function countWords(text: string): number;
80
+ /** The server's cap on a session id. Longer than this and the row is rejected. */
81
+ export declare const PROMPT_SESSION_ID_MAX_CHARS = 128;
82
+ /** One prompt, reduced to the three facts the activity aggregate needs. */
83
+ export type PromptLine = {
84
+ sessionId: string;
85
+ /** Canonical ISO-8601 UTC, so string order is time order. */
86
+ timestamp: string;
87
+ words: number;
88
+ };
37
89
  /**
38
- * The overflow threshold for this user's own distribution: their p90 prompt
39
- * length rounded up to a multiple of 10, clamped to [10, 100].
90
+ * A transcript line as prompt activity, or null when it isn't one.
91
+ *
92
+ * Stricter than `promptTextFrom` on purpose: a prompt with no session id or no
93
+ * usable timestamp can't be placed on a session or a day, and the server's
94
+ * schema would reject it, so it counts towards the histogram (which needs
95
+ * neither) and nothing else.
96
+ */
97
+ export declare function parsePromptLine(line: string): PromptLine | null;
98
+ /** An ISO-8601 UTC string, or null when the value isn't a usable instant. */
99
+ export declare function normalizeTimestamp(value: unknown): string | null;
100
+ export declare function emptyPromptActivity(): PromptActivityAggregate;
101
+ /**
102
+ * Fold one prompt into an activity aggregate, returning the session and date it
103
+ * landed on so an incremental caller can mark exactly those dirty.
104
+ *
105
+ * The date is the UTC day of the timestamp — the same attribution
106
+ * `toDateStr` gives every token daily row, so the two halves of a sync agree
107
+ * about which day a piece of work belongs to.
108
+ */
109
+ export declare function addPromptToActivity(activity: PromptActivityAggregate, line: PromptLine): {
110
+ sessionId: string;
111
+ date: string;
112
+ };
113
+ /**
114
+ * Where the histogram's axis ends for this user's own distribution: their p90
115
+ * prompt length rounded up to a multiple of 10, clamped to [10, 100]. Anything
116
+ * longer is reported by `buildTail` instead.
40
117
  *
41
118
  * Per-user rather than fixed because prompt length varies enormously between
42
119
  * people — a fixed axis would either crush a terse user's histogram into the
@@ -44,14 +121,40 @@ export declare function countWords(text: string): number;
44
121
  */
45
122
  export declare function bucketMaxFor(wordCounts: number[]): number;
46
123
  /**
47
- * Bucket the word counts. Buckets `1..bucketMax-1` are exact word counts; the
48
- * bucket at `bucketMax` is the overflow, holding every prompt that long or
49
- * longer. Empty buckets are omitted — the chart fills the gaps.
124
+ * Bucket the word counts. Every bucket `1..bucketMax` is an exact word count —
125
+ * there is no overflow bar. Empty buckets are omitted; the chart fills the gaps.
126
+ *
127
+ * Prompts longer than `bucketMax` are not in here at all: they are reported by
128
+ * `buildTail`, and only there. So the histogram and the tail partition the
129
+ * scan — sum(histogram counts) + sum(tail counts) === totalPrompts, always.
50
130
  */
51
131
  export declare function buildHistogram(wordCounts: number[], bucketMax: number): {
52
132
  length: number;
53
133
  count: number;
54
134
  }[];
135
+ /**
136
+ * The exact distribution of everything *longer* than `bucketMax`, which the
137
+ * histogram does not cover at all. One entry per distinct word count,
138
+ * ascending; empty (never absent) when nothing exceeds `bucketMax` — the
139
+ * field's presence on the wire is the marker that the histogram's bars are
140
+ * exact.
141
+ *
142
+ * Lengths only — no prompt text is involved here, or anywhere near it.
143
+ *
144
+ * A machine with a long history can have thousands of distinct long lengths,
145
+ * far past what the server accepts, so an over-cap tail is coarsened: lengths
146
+ * are rounded to multiples of 2, then 4, 8, … until at most
147
+ * `PROMPT_TAIL_MAX_ENTRIES` entries remain, summing the counts that collapse
148
+ * together. Rounding is *up* so that a coarsened entry still sits above
149
+ * `bucketMax` — rounding down could claim a length inside the histogram's own
150
+ * exact range for a prompt the histogram never counted.
151
+ *
152
+ * Deterministic: the result depends only on the multiset of word counts.
153
+ */
154
+ export declare function buildTail(wordCounts: number[], bucketMax: number): {
155
+ length: number;
156
+ count: number;
157
+ }[];
55
158
  /**
56
159
  * The `origin` remote of the repo at `cwd`, or null when there isn't one (not
57
160
  * a repo, no origin, no git binary, or the directory is gone). The URL is sent
@@ -69,4 +172,10 @@ export declare function gitOriginUrl(cwd: string): Promise<string | null>;
69
172
  export declare function scanPromptStats(options?: {
70
173
  includeSample?: boolean;
71
174
  }): Promise<PromptStats | null>;
175
+ /**
176
+ * The `promptStats` block as the server takes it. `activity` is deliberately
177
+ * dropped: it is local bookkeeping for the tick's incremental state, and it
178
+ * travels under its own top-level `promptActivity` field instead.
179
+ */
180
+ export declare function promptStatsPayload(stats: PromptStats): Omit<PromptStats, 'activity'>;
72
181
  //# sourceMappingURL=prompt-stats.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-stats.d.ts","sourceRoot":"","sources":["../src/prompt-stats.ts"],"names":[],"mappings":"AA6BA,mFAAmF;AACnF,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAC1C,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAC3C,oFAAoF;AACpF,eAAO,MAAM,iCAAiC,MAAM,CAAA;AACpD,8EAA8E;AAC9E,eAAO,MAAM,6BAA6B,QAAS,CAAA;AAEnD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC9C,QAAQ,EAAE,kBAAkB,EAAE,CAAA;IAC9B,mDAAmD;IACnD,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAwB5D;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAazD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAAE,EACpB,SAAS,EAAE,MAAM,GAChB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAUrC;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYtE;AAQD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAoF7B"}
1
+ {"version":3,"file":"prompt-stats.d.ts","sourceRoot":"","sources":["../src/prompt-stats.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,24 @@
1
1
  import { execFile } from 'node:child_process';
2
- import { readFile } from 'node:fs/promises';
2
+ import { readFile, stat } from 'node:fs/promises';
3
3
  import { homedir } from 'node:os';
4
4
  import { dirname, join } from 'node:path';
5
5
  import { promisify } from 'node:util';
6
- import { findFiles } from './scanners/util.js';
6
+ import { findFiles, toDateStr } from './scanners/util.js';
7
7
  /**
8
8
  * Prompt statistics, computed entirely on this machine from the local Claude
9
9
  * Code transcripts and uploaded only under an explicit consent tier (see
10
10
  * prompt-consent.ts).
11
11
  *
12
- * Two numbers come out of a scan:
12
+ * Three things come out of a full scan:
13
13
  *
14
- * - a histogram of how long the user's own prompts are, in words
14
+ * - a histogram of how long the user's own prompts are, in words — every
15
+ * bucket an exact word count — plus the tail, which is where the prompts
16
+ * longer than the axis are reported, and their only home
15
17
  * - a per-project prompt count, keyed by the project's git origin
18
+ * - the prompt *activity* aggregate: per-session start/end/count and a
19
+ * per-day prompt/word tally. That one is also what the minutely tick
20
+ * accumulates incrementally (scanners/incremental.ts), so a full scan can
21
+ * re-base the tick's state without either drifting from the other.
16
22
  *
17
23
  * and, under the `full` tier only, a sample of the raw prompt text so the
18
24
  * backend can score "how technical is this person's prompting". The backend
@@ -26,8 +32,10 @@ const execFileAsync = promisify(execFile);
26
32
  /** Buckets are `1..bucketMax`, so the axis stays readable at any prompt length. */
27
33
  export const PROMPT_LENGTH_BUCKET_MIN = 10;
28
34
  export const PROMPT_LENGTH_BUCKET_MAX = 100;
29
- /** The percentile that sets `bucketMax`; everything above lands in the overflow. */
30
- export const PROMPT_LENGTH_OVERFLOW_PERCENTILE = 0.9;
35
+ /** The percentile that sets `bucketMax`; everything above it lands in `tail`. */
36
+ export const PROMPT_LENGTH_AXIS_PERCENTILE = 0.9;
37
+ /** The server's cap on `tail` entries; longer distributions are coarsened. */
38
+ export const PROMPT_TAIL_MAX_ENTRIES = 400;
31
39
  /** Matches the backend's cap — anything longer is truncated before upload. */
32
40
  export const CONVERSATION_SAMPLE_MAX_CHARS = 20_000;
33
41
  /**
@@ -71,9 +79,93 @@ export function countWords(text) {
71
79
  const matches = text.match(/\S+/g);
72
80
  return matches ? matches.length : 0;
73
81
  }
82
+ /** The server's cap on a session id. Longer than this and the row is rejected. */
83
+ export const PROMPT_SESSION_ID_MAX_CHARS = 128;
74
84
  /**
75
- * The overflow threshold for this user's own distribution: their p90 prompt
76
- * length rounded up to a multiple of 10, clamped to [10, 100].
85
+ * A transcript line as prompt activity, or null when it isn't one.
86
+ *
87
+ * Stricter than `promptTextFrom` on purpose: a prompt with no session id or no
88
+ * usable timestamp can't be placed on a session or a day, and the server's
89
+ * schema would reject it, so it counts towards the histogram (which needs
90
+ * neither) and nothing else.
91
+ */
92
+ export function parsePromptLine(line) {
93
+ if (!line.trim())
94
+ return null;
95
+ let parsed;
96
+ try {
97
+ parsed = JSON.parse(line);
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ const text = promptTextFrom(parsed);
103
+ if (text === null)
104
+ return null;
105
+ const words = countWords(text);
106
+ if (words <= 0)
107
+ return null;
108
+ const entry = parsed;
109
+ const sessionId = typeof entry.sessionId === 'string' ? entry.sessionId.trim() : '';
110
+ if (!sessionId || sessionId.length > PROMPT_SESSION_ID_MAX_CHARS)
111
+ return null;
112
+ const timestamp = normalizeTimestamp(entry.timestamp);
113
+ if (!timestamp)
114
+ return null;
115
+ return { sessionId, timestamp, words };
116
+ }
117
+ /** An ISO-8601 UTC string, or null when the value isn't a usable instant. */
118
+ export function normalizeTimestamp(value) {
119
+ if (typeof value !== 'string' && typeof value !== 'number')
120
+ return null;
121
+ const at = typeof value === 'number' ? value : Date.parse(value);
122
+ if (!Number.isFinite(at))
123
+ return null;
124
+ return new Date(at).toISOString();
125
+ }
126
+ export function emptyPromptActivity() {
127
+ return { sessions: {}, daily: {} };
128
+ }
129
+ /**
130
+ * Fold one prompt into an activity aggregate, returning the session and date it
131
+ * landed on so an incremental caller can mark exactly those dirty.
132
+ *
133
+ * The date is the UTC day of the timestamp — the same attribution
134
+ * `toDateStr` gives every token daily row, so the two halves of a sync agree
135
+ * about which day a piece of work belongs to.
136
+ */
137
+ export function addPromptToActivity(activity, line) {
138
+ const session = activity.sessions[line.sessionId];
139
+ if (session) {
140
+ if (line.timestamp < session.startedAt)
141
+ session.startedAt = line.timestamp;
142
+ if (line.timestamp > session.lastActiveAt) {
143
+ session.lastActiveAt = line.timestamp;
144
+ }
145
+ session.promptCount += 1;
146
+ }
147
+ else {
148
+ activity.sessions[line.sessionId] = {
149
+ startedAt: line.timestamp,
150
+ lastActiveAt: line.timestamp,
151
+ promptCount: 1,
152
+ };
153
+ }
154
+ const date = toDateStr(line.timestamp);
155
+ const day = activity.daily[date];
156
+ if (day) {
157
+ day.prompts += 1;
158
+ day.words += line.words;
159
+ }
160
+ else {
161
+ activity.daily[date] = { prompts: 1, words: line.words };
162
+ }
163
+ return { sessionId: line.sessionId, date };
164
+ }
165
+ /**
166
+ * Where the histogram's axis ends for this user's own distribution: their p90
167
+ * prompt length rounded up to a multiple of 10, clamped to [10, 100]. Anything
168
+ * longer is reported by `buildTail` instead.
77
169
  *
78
170
  * Per-user rather than fixed because prompt length varies enormously between
79
171
  * people — a fixed axis would either crush a terse user's histogram into the
@@ -83,23 +175,72 @@ export function bucketMaxFor(wordCounts) {
83
175
  if (wordCounts.length === 0)
84
176
  return PROMPT_LENGTH_BUCKET_MIN;
85
177
  const sorted = [...wordCounts].sort((a, b) => a - b);
86
- const index = Math.min(sorted.length - 1, Math.floor(sorted.length * PROMPT_LENGTH_OVERFLOW_PERCENTILE));
178
+ const index = Math.min(sorted.length - 1, Math.floor(sorted.length * PROMPT_LENGTH_AXIS_PERCENTILE));
87
179
  const p90 = sorted[index] ?? PROMPT_LENGTH_BUCKET_MIN;
88
180
  const rounded = Math.ceil(p90 / 10) * 10;
89
181
  return Math.min(PROMPT_LENGTH_BUCKET_MAX, Math.max(PROMPT_LENGTH_BUCKET_MIN, rounded));
90
182
  }
91
183
  /**
92
- * Bucket the word counts. Buckets `1..bucketMax-1` are exact word counts; the
93
- * bucket at `bucketMax` is the overflow, holding every prompt that long or
94
- * longer. Empty buckets are omitted — the chart fills the gaps.
184
+ * Bucket the word counts. Every bucket `1..bucketMax` is an exact word count —
185
+ * there is no overflow bar. Empty buckets are omitted; the chart fills the gaps.
186
+ *
187
+ * Prompts longer than `bucketMax` are not in here at all: they are reported by
188
+ * `buildTail`, and only there. So the histogram and the tail partition the
189
+ * scan — sum(histogram counts) + sum(tail counts) === totalPrompts, always.
95
190
  */
96
191
  export function buildHistogram(wordCounts, bucketMax) {
97
192
  const counts = new Map();
98
193
  for (const words of wordCounts) {
99
194
  if (words <= 0)
100
195
  continue;
101
- const bucket = words >= bucketMax ? bucketMax : words;
102
- counts.set(bucket, (counts.get(bucket) ?? 0) + 1);
196
+ if (words > bucketMax)
197
+ continue;
198
+ counts.set(words, (counts.get(words) ?? 0) + 1);
199
+ }
200
+ return [...counts.entries()]
201
+ .map(([length, count]) => ({ length, count }))
202
+ .sort((a, b) => a.length - b.length);
203
+ }
204
+ /**
205
+ * The exact distribution of everything *longer* than `bucketMax`, which the
206
+ * histogram does not cover at all. One entry per distinct word count,
207
+ * ascending; empty (never absent) when nothing exceeds `bucketMax` — the
208
+ * field's presence on the wire is the marker that the histogram's bars are
209
+ * exact.
210
+ *
211
+ * Lengths only — no prompt text is involved here, or anywhere near it.
212
+ *
213
+ * A machine with a long history can have thousands of distinct long lengths,
214
+ * far past what the server accepts, so an over-cap tail is coarsened: lengths
215
+ * are rounded to multiples of 2, then 4, 8, … until at most
216
+ * `PROMPT_TAIL_MAX_ENTRIES` entries remain, summing the counts that collapse
217
+ * together. Rounding is *up* so that a coarsened entry still sits above
218
+ * `bucketMax` — rounding down could claim a length inside the histogram's own
219
+ * exact range for a prompt the histogram never counted.
220
+ *
221
+ * Deterministic: the result depends only on the multiset of word counts.
222
+ */
223
+ export function buildTail(wordCounts, bucketMax) {
224
+ const exact = new Map();
225
+ for (const words of wordCounts) {
226
+ if (words <= bucketMax)
227
+ continue;
228
+ exact.set(words, (exact.get(words) ?? 0) + 1);
229
+ }
230
+ if (exact.size === 0)
231
+ return [];
232
+ let counts = exact;
233
+ let step = 1;
234
+ while (counts.size > PROMPT_TAIL_MAX_ENTRIES) {
235
+ step *= 2;
236
+ const coarser = new Map();
237
+ // Always coarsen from the exact counts, so the rounding is one clean
238
+ // division rather than a rounding of a rounding.
239
+ for (const [length, count] of exact) {
240
+ const rounded = Math.ceil(length / step) * step;
241
+ coarser.set(rounded, (coarser.get(rounded) ?? 0) + count);
242
+ }
243
+ counts = coarser;
103
244
  }
104
245
  return [...counts.entries()]
105
246
  .map(([length, count]) => ({ length, count }))
@@ -121,6 +262,22 @@ export async function gitOriginUrl(cwd) {
121
262
  return null;
122
263
  }
123
264
  }
265
+ /**
266
+ * Newest transcript first. The sample is meant to be the user's *recent*
267
+ * prompting, so the walk order has to be time order — the directory walk's own
268
+ * order is alphabetical and would hand the scorer whatever happens to sort
269
+ * first, which for a long-lived machine is usually a project abandoned years
270
+ * ago. A file we can't stat sorts last rather than dropping out.
271
+ */
272
+ async function byMtimeDesc(paths) {
273
+ const stamped = await Promise.all(paths.map(async (path) => ({
274
+ path,
275
+ mtimeMs: await stat(path)
276
+ .then((s) => s.mtimeMs)
277
+ .catch(() => 0),
278
+ })));
279
+ return stamped.sort((a, b) => b.mtimeMs - a.mtimeMs).map((f) => f.path);
280
+ }
124
281
  /**
125
282
  * Scan the local Claude Code transcripts.
126
283
  *
@@ -130,10 +287,11 @@ export async function gitOriginUrl(cwd) {
130
287
  */
131
288
  export async function scanPromptStats(options = {}) {
132
289
  const root = join(homedir(), '.claude', 'projects');
133
- const files = await findFiles(root, '.jsonl');
290
+ const files = await byMtimeDesc(await findFiles(root, '.jsonl'));
134
291
  if (files.length === 0)
135
292
  return null;
136
293
  const wordCounts = [];
294
+ const activity = emptyPromptActivity();
137
295
  const sampleParts = [];
138
296
  let sampleChars = 0;
139
297
  // Keyed by the transcript's project directory, which is Claude Code's own
@@ -154,6 +312,12 @@ export async function scanPromptStats(options = {}) {
154
312
  catch {
155
313
  continue;
156
314
  }
315
+ // Within a file the newest prompts are last, so the sample is drained in
316
+ // reverse after the file is read. Only collected while the budget is still
317
+ // open, so a full sample doesn't hold a whole history in memory.
318
+ const collectSample = options.includeSample === true &&
319
+ sampleChars < CONVERSATION_SAMPLE_MAX_CHARS;
320
+ const fileSample = [];
157
321
  for (const line of content.split('\n')) {
158
322
  if (!line.trim())
159
323
  continue;
@@ -176,17 +340,22 @@ export async function scanPromptStats(options = {}) {
176
340
  continue;
177
341
  wordCounts.push(words);
178
342
  project.promptCount += 1;
179
- if (typeof entry.timestamp === 'string') {
180
- const at = Date.parse(entry.timestamp);
181
- if (Number.isFinite(at) && at > project.lastActiveAt) {
182
- project.lastActiveAt = at;
183
- }
184
- }
185
- if (options.includeSample &&
186
- sampleChars < CONVERSATION_SAMPLE_MAX_CHARS) {
187
- sampleParts.push(text);
188
- sampleChars += text.length + 2;
343
+ const at = Date.parse(String(entry.timestamp));
344
+ if (Number.isFinite(at) && at > project.lastActiveAt) {
345
+ project.lastActiveAt = at;
189
346
  }
347
+ const promptLine = parsePromptLine(line);
348
+ if (promptLine)
349
+ addPromptToActivity(activity, promptLine);
350
+ if (collectSample)
351
+ fileSample.push(text);
352
+ }
353
+ for (let i = fileSample.length - 1; i >= 0; i--) {
354
+ if (sampleChars >= CONVERSATION_SAMPLE_MAX_CHARS)
355
+ break;
356
+ const text = fileSample[i];
357
+ sampleParts.push(text);
358
+ sampleChars += text.length + 2;
190
359
  }
191
360
  }
192
361
  if (wordCounts.length === 0)
@@ -196,7 +365,9 @@ export async function scanPromptStats(options = {}) {
196
365
  totalPrompts: wordCounts.length,
197
366
  bucketMax,
198
367
  histogram: buildHistogram(wordCounts, bucketMax),
368
+ tail: buildTail(wordCounts, bucketMax),
199
369
  projects: await resolveProjects(byProjectDir),
370
+ activity,
200
371
  };
201
372
  if (options.includeSample && sampleParts.length > 0) {
202
373
  stats.conversationSample = sampleParts
@@ -205,6 +376,15 @@ export async function scanPromptStats(options = {}) {
205
376
  }
206
377
  return stats;
207
378
  }
379
+ /**
380
+ * The `promptStats` block as the server takes it. `activity` is deliberately
381
+ * dropped: it is local bookkeeping for the tick's incremental state, and it
382
+ * travels under its own top-level `promptActivity` field instead.
383
+ */
384
+ export function promptStatsPayload(stats) {
385
+ const { activity: _activity, ...wire } = stats;
386
+ return wire;
387
+ }
208
388
  /**
209
389
  * Turn the per-directory tallies into repo-keyed entries. Directories with no
210
390
  * prompts, no recorded `cwd`, or no git origin drop out — the backend can only
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-stats.js","sourceRoot":"","sources":["../src/prompt-stats.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prompt-stats.js","sourceRoot":"","sources":["../src/prompt-stats.ts"],"names":[],"mappings":"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"}