@peasant-labs/fairtrade 0.0.36 → 0.0.38

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.
@@ -1,4 +1,4 @@
1
- import { n as e, t } from "./ChartLine-Cycmpjep.js";
1
+ import { n as e, t } from "./ChartLine-MZVbpUu1.js";
2
2
  import { useMemo as n, useState as r } from "react";
3
3
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
4
  import { Activity as o, BarChart3 as s, ChevronDown as c, ChevronUp as l, ChevronsUpDown as u, CircleCheck as d, GitCommitHorizontal as f, Hash as p, PieChart as m, SlidersHorizontal as h, Timer as g, TrendingUp as ee, UserPlus as te, Users as _ } from "lucide-react";
@@ -36,28 +36,28 @@ function y(e) {
36
36
  let t = Math.round(e * 10) / 10;
37
37
  return Number.isInteger(t) ? String(t) : t.toFixed(1);
38
38
  }
39
- function ne(e) {
39
+ function b(e) {
40
40
  return e == null || !Number.isFinite(e) || e < 0 ? "—" : e < 1e3 ? String(Math.round(e)) : e < 1e6 ? `${y(e / 1e3)}k` : `${(e / 1e6).toFixed(2)}M`;
41
41
  }
42
- function b(e) {
42
+ function x(e) {
43
43
  if (e == null || !Number.isFinite(e)) return "—";
44
44
  let t = Math.round(e * 10) / 10;
45
45
  return Number.isInteger(t) ? String(t) : t.toFixed(1);
46
46
  }
47
- function x(e) {
47
+ function S(e) {
48
48
  return e == null || !Number.isFinite(e) ? "—" : `${Math.round(e * 100)}%`;
49
49
  }
50
- function S(e) {
50
+ function C(e) {
51
51
  if (e == null || !Number.isFinite(e) || e < 0) return "—";
52
52
  let t = Math.round(e);
53
53
  if (t < 60) return `${t}m`;
54
54
  let n = Math.floor(t / 60), r = t % 60;
55
55
  return r === 0 ? `${n}h` : `${n}h ${r}m`;
56
56
  }
57
- function re(e) {
57
+ function w(e) {
58
58
  return e.length >= 10 ? e.slice(5) : e;
59
59
  }
60
- function C(e, t) {
60
+ function T(e, t) {
61
61
  let n = [];
62
62
  for (let r of [e, t]) typeof r == "number" && Number.isFinite(r) && n.push(r);
63
63
  let r = n.some((e) => !Number.isInteger(Math.round(e * 10) / 10)), i = (e) => {
@@ -67,7 +67,7 @@ function C(e, t) {
67
67
  };
68
68
  return [i(e), i(t)];
69
69
  }
70
- function w(e, t) {
70
+ function E(e, t) {
71
71
  let n = [];
72
72
  for (let r of [e, t]) typeof r == "number" && Number.isFinite(r) && r >= 0 && n.push(r);
73
73
  if (n.length === 0) return ["—", "—"];
@@ -76,31 +76,31 @@ function w(e, t) {
76
76
  }
77
77
  //#endregion
78
78
  //#region src/ui/analytics/time.js
79
- function T(e) {
79
+ function D(e) {
80
80
  let t = Date.parse(e);
81
81
  return Number.isNaN(t) ? null : t;
82
82
  }
83
- var E = 864e5;
84
- function D(e) {
85
- let t = T(e);
83
+ var O = 864e5;
84
+ function k(e) {
85
+ let t = D(e);
86
86
  if (t === null) return null;
87
87
  let n = new Date(t), r = (n.getUTCDay() + 6) % 7;
88
- return k(/* @__PURE__ */ new Date(Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate()) - r * E));
88
+ return j(/* @__PURE__ */ new Date(Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate()) - r * O));
89
89
  }
90
- function O(e) {
91
- let t = T(e);
92
- return t === null ? null : k(new Date(t));
90
+ function A(e) {
91
+ let t = D(e);
92
+ return t === null ? null : j(new Date(t));
93
93
  }
94
- function k(e) {
94
+ function j(e) {
95
95
  return `${e.getUTCFullYear().toString().padStart(4, "0")}-${(e.getUTCMonth() + 1).toString().padStart(2, "0")}-${e.getUTCDate().toString().padStart(2, "0")}`;
96
96
  }
97
- function A(e, t) {
97
+ function M(e, t) {
98
98
  let n = Date.parse(`${e}T00:00:00Z`), r = Date.parse(`${t}T00:00:00Z`);
99
- return Number.isNaN(n) || Number.isNaN(r) ? NaN : Math.round((r - n) / E);
99
+ return Number.isNaN(n) || Number.isNaN(r) ? NaN : Math.round((r - n) / O);
100
100
  }
101
101
  //#endregion
102
102
  //#region src/ui/analytics/stats.js
103
- function j(e, t) {
103
+ function N(e, t) {
104
104
  let n = e.filter((e) => Number.isFinite(e)).sort((e, t) => e - t);
105
105
  if (n.length === 0) return null;
106
106
  if (n.length === 1) return n[0];
@@ -109,26 +109,26 @@ function j(e, t) {
109
109
  let o = r - i;
110
110
  return n[i] + (n[a] - n[i]) * o;
111
111
  }
112
- function M(e) {
113
- return j(e, .5);
112
+ function P(e) {
113
+ return N(e, .5);
114
114
  }
115
- function N(e) {
115
+ function F(e) {
116
116
  let t = e.filter((e) => Number.isFinite(e));
117
117
  return {
118
118
  count: t.length,
119
- median: M(t),
120
- p90: j(t, .9)
119
+ median: P(t),
120
+ p90: N(t, .9)
121
121
  };
122
122
  }
123
123
  //#endregion
124
124
  //#region src/ui/analytics/metrics.js
125
- function P(e) {
125
+ function I(e) {
126
126
  return typeof e.commitCount == "number" ? e.commitCount > 0 : e.hasCommit === !0;
127
127
  }
128
- function F(e) {
128
+ function L(e) {
129
129
  let t = /* @__PURE__ */ new Map();
130
130
  for (let n of e) {
131
- let e = D(n.startTime);
131
+ let e = k(n.startTime);
132
132
  e !== null && t.set(e, (t.get(e) ?? 0) + 1);
133
133
  }
134
134
  return [...t.entries()].map(([e, t]) => ({
@@ -136,11 +136,11 @@ function F(e) {
136
136
  count: t
137
137
  })).sort((e, t) => e.week.localeCompare(t.week));
138
138
  }
139
- function I(e) {
139
+ function R(e) {
140
140
  let t = /* @__PURE__ */ new Map();
141
141
  for (let n of e) {
142
142
  if (!n.contributorId) continue;
143
- let e = D(n.startTime);
143
+ let e = k(n.startTime);
144
144
  if (e === null) continue;
145
145
  let r = t.get(e);
146
146
  r || (r = /* @__PURE__ */ new Set(), t.set(e, r)), r.add(n.contributorId);
@@ -150,11 +150,11 @@ function I(e) {
150
150
  contributors: t.size
151
151
  })).sort((e, t) => e.week.localeCompare(t.week));
152
152
  }
153
- function L(e) {
153
+ function z(e) {
154
154
  let t = /* @__PURE__ */ new Map();
155
155
  for (let n of e) {
156
156
  if (!n.contributorId) continue;
157
- let e = D(n.startTime);
157
+ let e = k(n.startTime);
158
158
  if (e === null) continue;
159
159
  let r = t.get(n.contributorId);
160
160
  r || (r = /* @__PURE__ */ new Set(), t.set(n.contributorId, r)), r.add(e);
@@ -167,11 +167,11 @@ function L(e) {
167
167
  rate: n === 0 ? 0 : r / n
168
168
  };
169
169
  }
170
- var R = 7 * 864e5;
171
- function z(e) {
170
+ var ne = 7 * 864e5;
171
+ function B(e) {
172
172
  let t = /* @__PURE__ */ new Set();
173
173
  for (let n of e) {
174
- let e = D(n.startTime);
174
+ let e = k(n.startTime);
175
175
  e !== null && t.add(e);
176
176
  }
177
177
  let n = [...t].sort((e, t) => e.localeCompare(t));
@@ -183,7 +183,7 @@ function z(e) {
183
183
  let r = 1, i = n[0], a = n[0], o = 1, s = n[0];
184
184
  for (let e = 1; e < n.length; e++) {
185
185
  let t = Date.parse(`${n[e - 1]}T00:00:00Z`);
186
- Date.parse(`${n[e]}T00:00:00Z`) - t === R ? o += 1 : (o = 1, s = n[e]), o > r && (r = o, i = s, a = n[e]);
186
+ Date.parse(`${n[e]}T00:00:00Z`) - t === ne ? o += 1 : (o = 1, s = n[e]), o > r && (r = o, i = s, a = n[e]);
187
187
  }
188
188
  return {
189
189
  weeks: r,
@@ -191,18 +191,18 @@ function z(e) {
191
191
  endWeek: a
192
192
  };
193
193
  }
194
- function B(e) {
194
+ function V(e) {
195
195
  let t = /* @__PURE__ */ new Map();
196
196
  for (let n of e) {
197
197
  if (!n.contributorId) continue;
198
- let e = O(n.startTime);
198
+ let e = A(n.startTime);
199
199
  if (e === null) continue;
200
200
  let r = t.get(n.contributorId);
201
201
  (r === void 0 || e < r) && t.set(n.contributorId, e);
202
202
  }
203
203
  let n = /* @__PURE__ */ new Map();
204
204
  for (let e of t.values()) {
205
- let t = D(`${e}T00:00:00Z`);
205
+ let t = k(`${e}T00:00:00Z`);
206
206
  t !== null && n.set(t, (n.get(t) ?? 0) + 1);
207
207
  }
208
208
  return [...n.entries()].map(([e, t]) => ({
@@ -210,19 +210,19 @@ function B(e) {
210
210
  newContributors: t
211
211
  })).sort((e, t) => e.week.localeCompare(t.week));
212
212
  }
213
- function ie(e) {
213
+ function re(e) {
214
214
  let t = e.length, n = 0;
215
- for (let t of e) P(t) && (n += 1);
215
+ for (let t of e) I(t) && (n += 1);
216
216
  return {
217
217
  total: t,
218
218
  withCommit: n,
219
219
  rate: t === 0 ? 0 : n / t
220
220
  };
221
221
  }
222
- function ae(e) {
222
+ function ie(e) {
223
223
  let t = /* @__PURE__ */ new Map();
224
224
  for (let n of e) {
225
- let e = D(n.startTime);
225
+ let e = k(n.startTime);
226
226
  if (e === null || !Number.isFinite(n.durationMins)) continue;
227
227
  let r = t.get(e) ?? {
228
228
  sum: 0,
@@ -236,7 +236,7 @@ function ae(e) {
236
236
  sessions: n
237
237
  })).sort((e, t) => e.week.localeCompare(t.week));
238
238
  }
239
- function oe(e) {
239
+ function ae(e) {
240
240
  let t = {
241
241
  resolved: 0,
242
242
  partial: 0,
@@ -258,7 +258,7 @@ function oe(e) {
258
258
  }
259
259
  return t;
260
260
  }
261
- function se(e) {
261
+ function oe(e) {
262
262
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
263
263
  for (let r of e) {
264
264
  if (!r.contributorId) continue;
@@ -282,7 +282,7 @@ function se(e) {
282
282
  },
283
283
  firstSeen: null,
284
284
  lastSeen: null
285
- }, i = /* @__PURE__ */ new Set(), t.set(r.contributorId, e), n.set(r.contributorId, i)), e.sessions += 1, e.outcomes.total += 1, Number.isFinite(r.totalTokens) && (e.totalTokens += r.totalTokens), Number.isFinite(r.durationMins) && (e.totalDurationMins += r.durationMins), Number.isFinite(r.turnCount) && (e.totalTurns += r.turnCount), Number.isFinite(r.toolCallCount) && (e.totalToolCalls += r.toolCallCount), P(r) && (e.sessionsWithCommit += 1), typeof r.commitCount == "number" && Number.isFinite(r.commitCount) ? e.totalCommits += Math.max(0, r.commitCount) : r.hasCommit === !0 && (e.totalCommits += 1), r.outcome) {
285
+ }, i = /* @__PURE__ */ new Set(), t.set(r.contributorId, e), n.set(r.contributorId, i)), e.sessions += 1, e.outcomes.total += 1, Number.isFinite(r.totalTokens) && (e.totalTokens += r.totalTokens), Number.isFinite(r.durationMins) && (e.totalDurationMins += r.durationMins), Number.isFinite(r.turnCount) && (e.totalTurns += r.turnCount), Number.isFinite(r.toolCallCount) && (e.totalToolCalls += r.toolCallCount), I(r) && (e.sessionsWithCommit += 1), typeof r.commitCount == "number" && Number.isFinite(r.commitCount) ? e.totalCommits += Math.max(0, r.commitCount) : r.hasCommit === !0 && (e.totalCommits += 1), r.outcome) {
286
286
  case "resolved":
287
287
  e.outcomes.resolved += 1;
288
288
  break;
@@ -294,9 +294,9 @@ function se(e) {
294
294
  break;
295
295
  default: e.outcomes.unknown += 1;
296
296
  }
297
- let a = D(r.startTime);
297
+ let a = k(r.startTime);
298
298
  a !== null && i.add(a);
299
- let o = O(r.startTime);
299
+ let o = A(r.startTime);
300
300
  o !== null && ((e.firstSeen === null || o < e.firstSeen) && (e.firstSeen = o), (e.lastSeen === null || o > e.lastSeen) && (e.lastSeen = o));
301
301
  }
302
302
  return [...t.values()].map((e) => ({
@@ -304,40 +304,40 @@ function se(e) {
304
304
  activeWeeks: n.get(e.contributorId)?.size ?? 0
305
305
  })).sort((e, t) => t.sessions - e.sessions || e.contributorId.localeCompare(t.contributorId));
306
306
  }
307
- function V(e) {
307
+ function H(e) {
308
308
  let t = e.total - e.unknown;
309
309
  return t <= 0 ? null : e.resolved / t;
310
310
  }
311
- function ce(e) {
311
+ function se(e) {
312
312
  return {
313
- durationMins: N(e.map((e) => e.durationMins)),
314
- totalTokens: N(e.map((e) => e.totalTokens)),
315
- turnCount: N(e.map((e) => e.turnCount)),
316
- toolCallCount: N(e.map((e) => e.toolCallCount))
313
+ durationMins: F(e.map((e) => e.durationMins)),
314
+ totalTokens: F(e.map((e) => e.totalTokens)),
315
+ turnCount: F(e.map((e) => e.turnCount)),
316
+ toolCallCount: F(e.map((e) => e.toolCallCount))
317
317
  };
318
318
  }
319
- function H(e) {
319
+ function U(e) {
320
320
  let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set();
321
321
  for (let r of e) r.contributorId && t.add(r.contributorId), r.projectKey && n.add(r.projectKey);
322
322
  return {
323
323
  totalSessions: e.length,
324
324
  totalContributors: t.size,
325
325
  totalProjects: n.size,
326
- sessionsPerWeek: F(e),
327
- weeklyActiveContributors: I(e),
328
- returningContributorRate: L(e),
329
- longestStreak: z(e),
330
- newContributorVelocity: B(e),
331
- sessionToCommitRate: ie(e),
332
- avgDurationPerActiveWeek: ae(e),
333
- outcomeDistribution: oe(e),
334
- sessionStats: ce(e),
335
- perContributorBreakdown: se(e)
326
+ sessionsPerWeek: L(e),
327
+ weeklyActiveContributors: R(e),
328
+ returningContributorRate: z(e),
329
+ longestStreak: B(e),
330
+ newContributorVelocity: V(e),
331
+ sessionToCommitRate: re(e),
332
+ avgDurationPerActiveWeek: ie(e),
333
+ outcomeDistribution: ae(e),
334
+ sessionStats: se(e),
335
+ perContributorBreakdown: oe(e)
336
336
  };
337
337
  }
338
338
  //#endregion
339
339
  //#region src/ui/analytics/ContributorTable.jsx
340
- var U = [
340
+ var W = [
341
341
  {
342
342
  key: "contributor",
343
343
  label: "contributor",
@@ -378,12 +378,12 @@ var U = [
378
378
  key: "resolved",
379
379
  label: "resolved",
380
380
  numeric: !0,
381
- value: (e) => V(e.outcomes) ?? -1
381
+ value: (e) => H(e.outcomes) ?? -1
382
382
  }
383
383
  ];
384
- function W({ rows: e, renderContributor: t, limit: o, className: s }) {
384
+ function G({ rows: e, renderContributor: t, limit: o, className: s }) {
385
385
  let [d, f] = r("sessions"), [p, m] = r("desc"), h = n(() => {
386
- let t = U.find((e) => e.key === d) ?? U[1], n = [...e].sort((e, n) => {
386
+ let t = W.find((e) => e.key === d) ?? W[1], n = [...e].sort((e, n) => {
387
387
  let r = t.value(e), i = t.value(n), a = typeof r == "number" && typeof i == "number" ? r - i : String(r).localeCompare(String(i));
388
388
  return a === 0 ? e.contributorId.localeCompare(n.contributorId) : p === "desc" ? -a : a;
389
389
  });
@@ -400,7 +400,7 @@ function W({ rows: e, renderContributor: t, limit: o, className: s }) {
400
400
  className: ["tbl-wrap", s].filter(Boolean).join(" "),
401
401
  children: /* @__PURE__ */ a("table", {
402
402
  className: "tbl",
403
- children: [/* @__PURE__ */ i("thead", { children: /* @__PURE__ */ i("tr", { children: U.map((e) => {
403
+ children: [/* @__PURE__ */ i("thead", { children: /* @__PURE__ */ i("tr", { children: W.map((e) => {
404
404
  let t = d === e.key, n = t ? p === "desc" ? c : l : u;
405
405
  return /* @__PURE__ */ i("th", {
406
406
  className: ["tbl-th", e.numeric && "tbl-right"].filter(Boolean).join(" "),
@@ -450,14 +450,14 @@ function W({ rows: e, renderContributor: t, limit: o, className: s }) {
450
450
  className: "tbl-td tbl-right",
451
451
  children: /* @__PURE__ */ i("span", {
452
452
  className: "tnum",
453
- children: ne(e.totalTokens)
453
+ children: b(e.totalTokens)
454
454
  })
455
455
  }),
456
456
  /* @__PURE__ */ i("td", {
457
457
  className: "tbl-td tbl-right",
458
458
  children: /* @__PURE__ */ i("span", {
459
459
  className: "tnum",
460
- children: S(e.totalDurationMins)
460
+ children: C(e.totalDurationMins)
461
461
  })
462
462
  }),
463
463
  /* @__PURE__ */ i("td", {
@@ -471,13 +471,13 @@ function W({ rows: e, renderContributor: t, limit: o, className: s }) {
471
471
  className: "tbl-td tbl-right",
472
472
  children: /* @__PURE__ */ i("span", {
473
473
  className: "tnum",
474
- children: V(e.outcomes) == null ? "—" : x(V(e.outcomes))
474
+ children: H(e.outcomes) == null ? "—" : S(H(e.outcomes))
475
475
  })
476
476
  })
477
477
  ]
478
478
  }, e.contributorId)), h.length === 0 && /* @__PURE__ */ i("tr", { children: /* @__PURE__ */ i("td", {
479
479
  className: "tbl-empty",
480
- colSpan: U.length,
480
+ colSpan: W.length,
481
481
  children: "no contributor data."
482
482
  }) })] })]
483
483
  })
@@ -485,11 +485,11 @@ function W({ rows: e, renderContributor: t, limit: o, className: s }) {
485
485
  }
486
486
  //#endregion
487
487
  //#region src/ui/analytics/types.js
488
- var le = Object.freeze([
488
+ var ce = Object.freeze([
489
489
  "resolved",
490
490
  "partial",
491
491
  "failed"
492
- ]), G = Object.freeze([
492
+ ]), K = Object.freeze([
493
493
  {
494
494
  key: "summary",
495
495
  label: "summary"
@@ -522,7 +522,7 @@ var le = Object.freeze([
522
522
  key: "contributorTable",
523
523
  label: "table"
524
524
  }
525
- ]), K = Object.freeze(G.map((e) => e.key)), ue = Object.fromEntries(K.map((e) => [e, !0])), de = [
525
+ ]), q = Object.freeze(K.map((e) => e.key)), le = Object.fromEntries(q.map((e) => [e, !0])), ue = [
526
526
  {
527
527
  key: "resolved",
528
528
  label: "resolved",
@@ -543,31 +543,31 @@ var le = Object.freeze([
543
543
  label: "unknown",
544
544
  token: "var(--ink-3)"
545
545
  }
546
- ], fe = [];
547
- function pe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle: y = !0, contributorLimit: re, renderContributor: C, chartHeight: w = 200, footnote: T, className: E }) {
548
- let D = c?.sessions ?? fe, O = c?.analytics, [k, A] = r(() => ue), [j, M] = r("active"), N = n(() => ({
549
- ...ue,
546
+ ], de = [];
547
+ function fe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle: y = !0, contributorLimit: w, renderContributor: T, chartHeight: E = 200, footnote: D, className: O }) {
548
+ let k = c?.sessions ?? de, A = c?.analytics, [j, M] = r(() => le), [N, P] = r("active"), F = n(() => ({
549
+ ...le,
550
550
  ...h
551
- }), [h]), P = n(() => Object.fromEntries(K.map((e) => [e, N[e] && k[e]])), [N, k]), F = n(() => O ?? H(D), [O, D]), I = n(() => ve(D, F), [F, D]), L = u ?? I, R = F.outcomeDistribution.total, z = F.perContributorBreakdown.reduce((e, t) => e + t.totalCommits, 0), B = P.newContributorVelocity ? j : "active";
551
+ }), [h]), I = n(() => Object.fromEntries(q.map((e) => [e, F[e] && j[e]])), [F, j]), L = n(() => A ?? U(k), [A, k]), R = n(() => _e(k, L), [L, k]), z = u ?? R, ne = L.outcomeDistribution.total, B = L.perContributorBreakdown.reduce((e, t) => e + t.totalCommits, 0), V = I.newContributorVelocity ? N : "active";
552
552
  return /* @__PURE__ */ a("div", {
553
- className: ["gan-root", E].filter(Boolean).join(" "),
554
- children: [l != null || L != null || y ? /* @__PURE__ */ a("div", {
553
+ className: ["gan-root", O].filter(Boolean).join(" "),
554
+ children: [l != null || z != null || y ? /* @__PURE__ */ a("div", {
555
555
  className: "gan-head",
556
556
  children: [/* @__PURE__ */ a("div", {
557
557
  className: "gan-head-titles",
558
558
  children: [l == null ? null : /* @__PURE__ */ i("h2", {
559
559
  className: "gan-h2",
560
560
  children: l
561
- }), L == null ? null : /* @__PURE__ */ i("div", {
561
+ }), z == null ? null : /* @__PURE__ */ i("div", {
562
562
  className: "gan-sub",
563
- children: L
563
+ children: z
564
564
  })]
565
- }), y ? /* @__PURE__ */ i(me, {
566
- baseSections: N,
567
- sections: P,
568
- userSections: k,
565
+ }), y ? /* @__PURE__ */ i(pe, {
566
+ baseSections: F,
567
+ sections: I,
568
+ userSections: j,
569
569
  onToggle: (e) => {
570
- A((t) => ({
570
+ M((t) => ({
571
571
  ...t,
572
572
  [e]: !t[e]
573
573
  }));
@@ -576,84 +576,84 @@ function pe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle:
576
576
  }) : null, /* @__PURE__ */ a("div", {
577
577
  className: "gan-scroll",
578
578
  children: [
579
- P.summary ? /* @__PURE__ */ a("div", {
579
+ I.summary ? /* @__PURE__ */ a("div", {
580
580
  className: "gan-kpis",
581
581
  role: "list",
582
582
  "aria-label": "headline metrics",
583
583
  children: [
584
- /* @__PURE__ */ i(q, {
584
+ /* @__PURE__ */ i(J, {
585
585
  icon: o,
586
586
  label: "new sessions",
587
- value: b(F.totalSessions),
587
+ value: x(L.totalSessions),
588
588
  hint: "recorded",
589
- detail: F.sessionsPerWeek.map((e) => `${e.week}: ${b(e.count)} sessions`).join("\n") || "no recorded weeks"
589
+ detail: L.sessionsPerWeek.map((e) => `${e.week}: ${x(e.count)} sessions`).join("\n") || "no recorded weeks"
590
590
  }),
591
- /* @__PURE__ */ i(q, {
591
+ /* @__PURE__ */ i(J, {
592
592
  icon: _,
593
593
  label: "contributors",
594
- value: b(F.totalContributors),
595
- hint: ye(F.perContributorBreakdown),
596
- detail: F.perContributorBreakdown.map((e) => `${e.contributorId}: ${b(e.sessions)} sessions`).join("\n") || "no recorded contributors"
594
+ value: x(L.totalContributors),
595
+ hint: ye(L.perContributorBreakdown),
596
+ detail: L.perContributorBreakdown.map((e) => `${e.contributorId}: ${x(e.sessions)} sessions`).join("\n") || "no recorded contributors"
597
597
  }),
598
- /* @__PURE__ */ i(q, {
598
+ /* @__PURE__ */ i(J, {
599
599
  icon: ee,
600
600
  label: "contributors in multiple weeks",
601
- value: x(F.returningContributorRate.rate),
602
- hint: `${b(F.returningContributorRate.returning)} of ${b(F.returningContributorRate.total)}`,
603
- detail: `${b(F.returningContributorRate.returning)} returning contributors active in two or more weeks; ${b(F.returningContributorRate.total)} contributors with dated sessions.`
601
+ value: S(L.returningContributorRate.rate),
602
+ hint: `${x(L.returningContributorRate.returning)} of ${x(L.returningContributorRate.total)}`,
603
+ detail: `${x(L.returningContributorRate.returning)} returning contributors active in two or more weeks; ${x(L.returningContributorRate.total)} contributors with dated sessions.`
604
604
  }),
605
- /* @__PURE__ */ i(q, {
605
+ /* @__PURE__ */ i(J, {
606
606
  icon: f,
607
607
  label: "sessions linked to commits",
608
- value: x(F.sessionToCommitRate.rate),
609
- hint: `${b(F.sessionToCommitRate.withCommit)} of ${b(F.sessionToCommitRate.total)}`,
610
- detail: `${b(F.sessionToCommitRate.withCommit)} sessions linked to a commit; ${b(F.sessionToCommitRate.total - F.sessionToCommitRate.withCommit)} without a linked commit.`
608
+ value: S(L.sessionToCommitRate.rate),
609
+ hint: `${x(L.sessionToCommitRate.withCommit)} of ${x(L.sessionToCommitRate.total)}`,
610
+ detail: `${x(L.sessionToCommitRate.withCommit)} sessions linked to a commit; ${x(L.sessionToCommitRate.total - L.sessionToCommitRate.withCommit)} without a linked commit.`
611
611
  }),
612
- /* @__PURE__ */ i(q, {
612
+ /* @__PURE__ */ i(J, {
613
613
  icon: d,
614
614
  label: "weeks with sessions",
615
- detail: F.sessionsPerWeek.filter((e) => e.count > 0).map((e) => e.week).join("\n") || "no weeks with sessions",
616
- value: `${b(F.sessionsPerWeek.filter((e) => e.count > 0).length)} wk`
615
+ detail: L.sessionsPerWeek.filter((e) => e.count > 0).map((e) => e.week).join("\n") || "no weeks with sessions",
616
+ value: `${x(L.sessionsPerWeek.filter((e) => e.count > 0).length)} wk`
617
617
  }),
618
- /* @__PURE__ */ i(q, {
618
+ /* @__PURE__ */ i(J, {
619
619
  icon: p,
620
620
  label: "projects",
621
- value: b(F.totalProjects),
622
- hint: X(D, F.totalProjects),
623
- detail: [...new Set(D.map((e) => e.project).filter(Boolean))].join("\n") || `${b(F.totalProjects)} projects in the supplied summary.`
621
+ value: x(L.totalProjects),
622
+ hint: ve(k, L.totalProjects),
623
+ detail: [...new Set(k.map((e) => e.project).filter(Boolean))].join("\n") || `${x(L.totalProjects)} projects in the supplied summary.`
624
624
  })
625
625
  ]
626
626
  }) : null,
627
627
  /* @__PURE__ */ a("div", {
628
628
  className: "gan-grid",
629
629
  children: [
630
- P.sessionsPerWeek ? /* @__PURE__ */ i(v, {
630
+ I.sessionsPerWeek ? /* @__PURE__ */ i(v, {
631
631
  icon: s,
632
632
  title: "sessions per week",
633
- aside: `${b(F.totalSessions)} total`,
633
+ aside: `${x(L.totalSessions)} total`,
634
634
  children: /* @__PURE__ */ i(e, {
635
- data: J(Q(F.sessionsPerWeek, "count")),
635
+ data: Y(Q(L.sessionsPerWeek, "count")),
636
636
  xKey: "label",
637
637
  series: [{
638
638
  key: "value",
639
639
  name: "sessions",
640
640
  color: "amber"
641
641
  }],
642
- height: w,
643
- valueFormatter: b
642
+ height: E,
643
+ valueFormatter: x
644
644
  })
645
645
  }) : null,
646
- P.weeklyActiveContributors ? /* @__PURE__ */ i(v, {
646
+ I.weeklyActiveContributors ? /* @__PURE__ */ i(v, {
647
647
  icon: _,
648
648
  title: "weekly active contributors",
649
- subtitle: B === "new" ? `${b($(Q(F.newContributorVelocity, "newContributors")))} new` : `${b($(Q(F.weeklyActiveContributors, "contributors")))} active`,
650
- aside: /* @__PURE__ */ i(he, {
651
- view: B,
652
- canShowNew: !!P.newContributorVelocity,
653
- onChange: M
649
+ subtitle: V === "new" ? `${x($(Q(L.newContributorVelocity, "newContributors")))} new` : `${x($(Q(L.weeklyActiveContributors, "contributors")))} active`,
650
+ aside: /* @__PURE__ */ i(me, {
651
+ view: V,
652
+ canShowNew: !!I.newContributorVelocity,
653
+ onChange: P
654
654
  }),
655
- children: B === "new" ? /* @__PURE__ */ i(t, {
656
- data: J(Q(F.newContributorVelocity, "newContributors")),
655
+ children: V === "new" ? /* @__PURE__ */ i(t, {
656
+ data: Y(Q(L.newContributorVelocity, "newContributors")),
657
657
  xKey: "label",
658
658
  series: [{
659
659
  key: "value",
@@ -661,10 +661,10 @@ function pe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle:
661
661
  color: "olive",
662
662
  area: !0
663
663
  }],
664
- height: w,
665
- valueFormatter: b
664
+ height: E,
665
+ valueFormatter: x
666
666
  }) : /* @__PURE__ */ i(t, {
667
- data: J(Q(F.weeklyActiveContributors, "contributors")),
667
+ data: Y(Q(L.weeklyActiveContributors, "contributors")),
668
668
  xKey: "label",
669
669
  series: [{
670
670
  key: "value",
@@ -672,67 +672,67 @@ function pe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle:
672
672
  color: "teal",
673
673
  area: !0
674
674
  }],
675
- height: w,
676
- valueFormatter: b
675
+ height: E,
676
+ valueFormatter: x
677
677
  })
678
678
  }) : null,
679
- P.newContributorVelocity ? /* @__PURE__ */ i(v, {
679
+ I.newContributorVelocity ? /* @__PURE__ */ i(v, {
680
680
  icon: te,
681
681
  title: "new contributors per week",
682
- aside: `${b($(Q(F.newContributorVelocity, "newContributors")))} new`,
682
+ aside: `${x($(Q(L.newContributorVelocity, "newContributors")))} new`,
683
683
  children: /* @__PURE__ */ i(e, {
684
- data: J(Q(F.newContributorVelocity, "newContributors")),
684
+ data: Y(Q(L.newContributorVelocity, "newContributors")),
685
685
  xKey: "label",
686
686
  series: [{
687
687
  key: "value",
688
688
  name: "new contributors",
689
689
  color: "olive"
690
690
  }],
691
- height: w,
692
- valueFormatter: b
691
+ height: E,
692
+ valueFormatter: x
693
693
  })
694
694
  }) : null,
695
- P.avgDurationPerActiveWeek ? /* @__PURE__ */ i(v, {
695
+ I.avgDurationPerActiveWeek ? /* @__PURE__ */ i(v, {
696
696
  icon: g,
697
697
  title: "avg duration per active week",
698
698
  subtitle: "minutes",
699
- aside: `${S(xe(Q(F.avgDurationPerActiveWeek, "avgDurationMins")))} avg`,
699
+ aside: `${C(xe(Q(L.avgDurationPerActiveWeek, "avgDurationMins")))} avg`,
700
700
  children: /* @__PURE__ */ i(t, {
701
- data: J(Q(F.avgDurationPerActiveWeek, "avgDurationMins")),
701
+ data: Y(Q(L.avgDurationPerActiveWeek, "avgDurationMins")),
702
702
  xKey: "label",
703
703
  series: [{
704
704
  key: "value",
705
705
  name: "minutes",
706
706
  color: "amber"
707
707
  }],
708
- height: w,
709
- valueFormatter: b
708
+ height: E,
709
+ valueFormatter: x
710
710
  })
711
711
  }) : null,
712
- P.outcomeDistribution ? /* @__PURE__ */ i(v, {
712
+ I.outcomeDistribution ? /* @__PURE__ */ i(v, {
713
713
  icon: m,
714
714
  title: "outcome distribution",
715
- aside: `${b(R)} total`,
716
- children: /* @__PURE__ */ i(ge, { data: F.outcomeDistribution })
715
+ aside: `${x(ne)} total`,
716
+ children: /* @__PURE__ */ i(he, { data: L.outcomeDistribution })
717
717
  }) : null,
718
- P.sessionStats ? /* @__PURE__ */ i(v, {
718
+ I.sessionStats ? /* @__PURE__ */ i(v, {
719
719
  icon: o,
720
720
  title: "typical vs. tail",
721
721
  subtitle: "median, p90",
722
722
  aside: "per session",
723
- children: /* @__PURE__ */ i(_e, { data: F.sessionStats })
723
+ children: /* @__PURE__ */ i(ge, { data: L.sessionStats })
724
724
  }) : null
725
725
  ]
726
726
  }),
727
- P.contributorTable ? /* @__PURE__ */ a(v, {
727
+ I.contributorTable ? /* @__PURE__ */ a(v, {
728
728
  icon: _,
729
729
  title: "contributors",
730
- aside: `${b(F.perContributorBreakdown.length)} people`,
730
+ aside: `${x(L.perContributorBreakdown.length)} ${Z(L.perContributorBreakdown.length, "person", "people")}`,
731
731
  className: "gan-tablecard",
732
- children: [/* @__PURE__ */ i(W, {
733
- rows: F.perContributorBreakdown,
734
- limit: re,
735
- renderContributor: C
732
+ children: [/* @__PURE__ */ i(G, {
733
+ rows: L.perContributorBreakdown,
734
+ limit: w,
735
+ renderContributor: T
736
736
  }), /* @__PURE__ */ a("div", {
737
737
  className: "gan-table-foot",
738
738
  children: [
@@ -741,7 +741,7 @@ function pe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle:
741
741
  children: [
742
742
  /* @__PURE__ */ i(p, { "aria-hidden": "true" }),
743
743
  " totals ",
744
- /* @__PURE__ */ i("b", { children: b(F.totalSessions) }),
744
+ /* @__PURE__ */ i("b", { children: x(L.totalSessions) }),
745
745
  " sessions"
746
746
  ]
747
747
  }),
@@ -750,7 +750,7 @@ function pe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle:
750
750
  children: [
751
751
  /* @__PURE__ */ i(p, { "aria-hidden": "true" }),
752
752
  " ",
753
- /* @__PURE__ */ i("b", { children: ne(Se(F.perContributorBreakdown)) }),
753
+ /* @__PURE__ */ i("b", { children: b(Se(L.perContributorBreakdown)) }),
754
754
  " tokens"
755
755
  ]
756
756
  }),
@@ -759,23 +759,23 @@ function pe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle:
759
759
  children: [
760
760
  /* @__PURE__ */ i(f, { "aria-hidden": "true" }),
761
761
  " ",
762
- /* @__PURE__ */ i("b", { children: b(z) }),
762
+ /* @__PURE__ */ i("b", { children: x(B) }),
763
763
  " commits"
764
764
  ]
765
765
  })
766
766
  ]
767
767
  })]
768
768
  }) : null,
769
- T == null ? null : /* @__PURE__ */ i("p", {
769
+ D == null ? null : /* @__PURE__ */ i("p", {
770
770
  className: "gan-foot",
771
- children: T
771
+ children: D
772
772
  })
773
773
  ]
774
774
  })]
775
775
  });
776
776
  }
777
- function me({ baseSections: e, sections: t, userSections: n, onToggle: r }) {
778
- let o = G.filter((e) => t[e.key]).length;
777
+ function pe({ baseSections: e, sections: t, userSections: n, onToggle: r }) {
778
+ let o = K.filter((e) => t[e.key]).length;
779
779
  return /* @__PURE__ */ a("div", {
780
780
  className: "gan-toggle",
781
781
  role: "group",
@@ -793,13 +793,13 @@ function me({ baseSections: e, sections: t, userSections: n, onToggle: r }) {
793
793
  children: [
794
794
  o,
795
795
  "/",
796
- G.length
796
+ K.length
797
797
  ]
798
798
  })
799
799
  ]
800
800
  }), /* @__PURE__ */ i("div", {
801
801
  className: "gan-toggle-chips",
802
- children: G.map((t) => {
802
+ children: K.map((t) => {
803
803
  let a = e[t.key], o = a && n[t.key];
804
804
  return /* @__PURE__ */ i("button", {
805
805
  type: "button",
@@ -814,7 +814,7 @@ function me({ baseSections: e, sections: t, userSections: n, onToggle: r }) {
814
814
  })]
815
815
  });
816
816
  }
817
- function he({ view: e, canShowNew: t, onChange: n }) {
817
+ function me({ view: e, canShowNew: t, onChange: n }) {
818
818
  return /* @__PURE__ */ a("div", {
819
819
  className: "gan-toggle-chips",
820
820
  role: "group",
@@ -835,7 +835,7 @@ function he({ view: e, canShowNew: t, onChange: n }) {
835
835
  })]
836
836
  });
837
837
  }
838
- function q({ icon: e, label: t, value: n, hint: r, detail: o }) {
838
+ function J({ icon: e, label: t, value: n, hint: r, detail: o }) {
839
839
  return /* @__PURE__ */ i("div", {
840
840
  className: "gan-tile",
841
841
  role: "listitem",
@@ -865,19 +865,19 @@ function q({ icon: e, label: t, value: n, hint: r, detail: o }) {
865
865
  })] })
866
866
  });
867
867
  }
868
- function J(e) {
868
+ function Y(e) {
869
869
  return e.map((e) => ({
870
870
  label: e.label,
871
871
  value: e.value
872
872
  }));
873
873
  }
874
- function ge({ data: e }) {
874
+ function he({ data: e }) {
875
875
  let [t, n] = r(null), o = e.total;
876
876
  if (o === 0) return /* @__PURE__ */ i("div", {
877
877
  className: "gan-donut-empty",
878
878
  children: "no outcome data."
879
879
  });
880
- let s = de.map((t) => ({
880
+ let s = ue.map((t) => ({
881
881
  ...t,
882
882
  value: e[t.key]
883
883
  })).filter((e) => e.value > 0), c = .045, l = -Math.PI / 2, u = s.map((e) => {
@@ -896,7 +896,7 @@ function ge({ data: e }) {
896
896
  className: "gan-donut-svg",
897
897
  viewBox: "0 0 180 180",
898
898
  role: "img",
899
- "aria-label": `outcome distribution across ${b(o)} sessions`,
899
+ "aria-label": `outcome distribution across ${x(o)} sessions`,
900
900
  children: [
901
901
  u.map((e, r) => /* @__PURE__ */ i("path", {
902
902
  d: e.d,
@@ -907,7 +907,7 @@ function ge({ data: e }) {
907
907
  className: "gan-slice",
908
908
  tabIndex: 0,
909
909
  role: "img",
910
- "aria-label": `${e.label}, ${b(e.value)} sessions, ${x(e.frac)}`,
910
+ "aria-label": `${e.label}, ${x(e.value)} sessions, ${S(e.frac)}`,
911
911
  onMouseEnter: () => n(r),
912
912
  onMouseLeave: () => n((e) => e === r ? null : e),
913
913
  onFocus: () => n(r),
@@ -918,7 +918,7 @@ function ge({ data: e }) {
918
918
  y: "84",
919
919
  className: "gan-donut-num tnum",
920
920
  textAnchor: "middle",
921
- children: b(t == null ? o : s[t].value)
921
+ children: x(t == null ? o : s[t].value)
922
922
  }),
923
923
  /* @__PURE__ */ i("text", {
924
924
  x: "90",
@@ -930,7 +930,7 @@ function ge({ data: e }) {
930
930
  ]
931
931
  }), /* @__PURE__ */ i("ul", {
932
932
  className: "gan-legend",
933
- children: de.map((r) => {
933
+ children: ue.map((r) => {
934
934
  let c = e[r.key], l = o === 0 ? 0 : c / o, u = s.findIndex((e) => e.key === r.key);
935
935
  return /* @__PURE__ */ a("li", {
936
936
  className: ["gan-legend-row", t === u && u >= 0 && "is-hot"].filter(Boolean).join(" "),
@@ -948,11 +948,11 @@ function ge({ data: e }) {
948
948
  }),
949
949
  /* @__PURE__ */ i("span", {
950
950
  className: "gan-legend-v tnum",
951
- children: b(c)
951
+ children: x(c)
952
952
  }),
953
953
  /* @__PURE__ */ i("span", {
954
954
  className: "gan-legend-pct tnum",
955
- children: x(l)
955
+ children: S(l)
956
956
  })
957
957
  ]
958
958
  }, r.key);
@@ -960,27 +960,27 @@ function ge({ data: e }) {
960
960
  })]
961
961
  });
962
962
  }
963
- function _e({ data: e }) {
964
- let [t, n] = w(e.totalTokens.median, e.totalTokens.p90), [r, o] = C(e.turnCount.median, e.turnCount.p90), [s, c] = C(e.toolCallCount.median, e.toolCallCount.p90);
963
+ function ge({ data: e }) {
964
+ let [t, n] = E(e.totalTokens.median, e.totalTokens.p90), [r, o] = T(e.turnCount.median, e.turnCount.p90), [s, c] = T(e.toolCallCount.median, e.toolCallCount.p90);
965
965
  return /* @__PURE__ */ a("div", {
966
966
  className: "gan-typical",
967
967
  children: [
968
- /* @__PURE__ */ i(Y, {
968
+ /* @__PURE__ */ i(X, {
969
969
  label: "duration",
970
- median: S(e.durationMins.median),
971
- p90: S(e.durationMins.p90)
970
+ median: C(e.durationMins.median),
971
+ p90: C(e.durationMins.p90)
972
972
  }),
973
- /* @__PURE__ */ i(Y, {
973
+ /* @__PURE__ */ i(X, {
974
974
  label: "tokens",
975
975
  median: t,
976
976
  p90: n
977
977
  }),
978
- /* @__PURE__ */ i(Y, {
978
+ /* @__PURE__ */ i(X, {
979
979
  label: "turns",
980
980
  median: r,
981
981
  p90: o
982
982
  }),
983
- /* @__PURE__ */ i(Y, {
983
+ /* @__PURE__ */ i(X, {
984
984
  label: "tool calls",
985
985
  median: s,
986
986
  p90: c
@@ -988,7 +988,7 @@ function _e({ data: e }) {
988
988
  ]
989
989
  });
990
990
  }
991
- function Y({ label: e, median: t, p90: n }) {
991
+ function X({ label: e, median: t, p90: n }) {
992
992
  return /* @__PURE__ */ a("div", {
993
993
  className: "gan-typrow",
994
994
  children: [/* @__PURE__ */ i("span", {
@@ -1004,7 +1004,7 @@ function Y({ label: e, median: t, p90: n }) {
1004
1004
  /* @__PURE__ */ i("span", {
1005
1005
  className: "gan-typsep",
1006
1006
  "aria-hidden": "true",
1007
- children: ","
1007
+ children: "/"
1008
1008
  }),
1009
1009
  /* @__PURE__ */ i("span", {
1010
1010
  className: "gan-typp90 tnum",
@@ -1014,16 +1014,16 @@ function Y({ label: e, median: t, p90: n }) {
1014
1014
  })]
1015
1015
  });
1016
1016
  }
1017
- function ve(e, t) {
1017
+ function _e(e, t) {
1018
1018
  return [
1019
- X(e, t.totalProjects),
1020
- `${b(t.totalContributors)} ${Z(t.totalContributors, "contributor", "contributors")}`,
1021
- `${b(t.totalSessions)} ${Z(t.totalSessions, "session", "sessions")} across ${b(t.sessionsPerWeek.length)} ${Z(t.sessionsPerWeek.length, "week", "weeks")}`
1019
+ ve(e, t.totalProjects),
1020
+ `${x(t.totalContributors)} ${Z(t.totalContributors, "contributor", "contributors")}`,
1021
+ `${x(t.totalSessions)} ${Z(t.totalSessions, "session", "sessions")} across ${x(t.sessionsPerWeek.length)} ${Z(t.sessionsPerWeek.length, "week", "weeks")}`
1022
1022
  ].join(", ");
1023
1023
  }
1024
- function X(e, t) {
1024
+ function ve(e, t) {
1025
1025
  let n = [...new Set(e.map((e) => e.projectKey).filter(Boolean))].sort();
1026
- return n.length === 0 ? t === 0 ? "no projects" : `${b(t)} ${Z(t, "project", "projects")}` : n.length === 1 ? n[0] : n.length <= 3 ? n.join(", ") : `${b(n.length)} projects`;
1026
+ return n.length === 0 ? t === 0 ? "no projects" : `${x(t)} ${Z(t, "project", "projects")}` : n.length === 1 ? n[0] : n.length <= 3 ? n.join(", ") : `${x(n.length)} projects`;
1027
1027
  }
1028
1028
  function ye(e) {
1029
1029
  if (e.length === 0) return "none";
@@ -1036,7 +1036,7 @@ function Z(e, t, n) {
1036
1036
  function Q(e, t) {
1037
1037
  return e.map((e) => ({
1038
1038
  key: e.week,
1039
- label: re(e.week),
1039
+ label: w(e.week),
1040
1040
  value: be(e[t])
1041
1041
  }));
1042
1042
  }
@@ -1053,4 +1053,4 @@ function Se(e) {
1053
1053
  return e.reduce((e, t) => e + t.totalTokens, 0);
1054
1054
  }
1055
1055
  //#endregion
1056
- export { le as ANALYTICS_SESSION_OUTCOMES, v as ChartCard, W as ContributorTable, G as PROJECT_OVERVIEW_SECTION_DEFS, K as PROJECT_OVERVIEW_SECTION_KEYS, pe as ProjectOverview, ae as avgDurationPerActiveWeek, H as computeProjectAnalytics, O as dayKey, A as daysBetween, k as isoDate, z as longestStreak, M as median, N as medianAndP90, B as newContributorVelocity, oe as outcomeDistribution, T as parseTime, se as perContributorBreakdown, j as percentile, V as resolvedRate, L as returningContributorRate, P as sessionHasCommit, ce as sessionStats, ie as sessionToCommitRate, F as sessionsPerWeek, D as weekKey, I as weeklyActiveContributors };
1056
+ export { ce as ANALYTICS_SESSION_OUTCOMES, v as ChartCard, G as ContributorTable, K as PROJECT_OVERVIEW_SECTION_DEFS, q as PROJECT_OVERVIEW_SECTION_KEYS, fe as ProjectOverview, ie as avgDurationPerActiveWeek, U as computeProjectAnalytics, A as dayKey, M as daysBetween, j as isoDate, B as longestStreak, P as median, F as medianAndP90, V as newContributorVelocity, ae as outcomeDistribution, D as parseTime, oe as perContributorBreakdown, N as percentile, H as resolvedRate, z as returningContributorRate, I as sessionHasCommit, se as sessionStats, re as sessionToCommitRate, L as sessionsPerWeek, k as weekKey, R as weeklyActiveContributors };