@aida-dev/metrics 0.1.7 → 0.3.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.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CommitStream } from '@aida-dev/core';
1
+ import { CommitStream, Commit } from '@aida-dev/core';
2
2
  import { z } from 'zod';
3
3
 
4
4
  declare const MergeRatio: z.ZodObject<{
@@ -62,6 +62,132 @@ declare const Persistence: z.ZodObject<{
62
62
  };
63
63
  }>;
64
64
  type Persistence = z.infer<typeof Persistence>;
65
+ declare const CohortMergeRatio: z.ZodObject<{
66
+ commitsTotal: z.ZodNumber;
67
+ commitsMerged: z.ZodNumber;
68
+ mergeRatio: z.ZodNumber;
69
+ }, "strip", z.ZodTypeAny, {
70
+ mergeRatio: number;
71
+ commitsTotal: number;
72
+ commitsMerged: number;
73
+ }, {
74
+ mergeRatio: number;
75
+ commitsTotal: number;
76
+ commitsMerged: number;
77
+ }>;
78
+ type CohortMergeRatio = z.infer<typeof CohortMergeRatio>;
79
+ declare const Baseline: z.ZodObject<{
80
+ mergeRatio: z.ZodObject<{
81
+ commitsTotal: z.ZodNumber;
82
+ commitsMerged: z.ZodNumber;
83
+ mergeRatio: z.ZodNumber;
84
+ }, "strip", z.ZodTypeAny, {
85
+ mergeRatio: number;
86
+ commitsTotal: number;
87
+ commitsMerged: number;
88
+ }, {
89
+ mergeRatio: number;
90
+ commitsTotal: number;
91
+ commitsMerged: number;
92
+ }>;
93
+ persistence: z.ZodObject<{
94
+ commitsConsidered: z.ZodNumber;
95
+ avgDays: z.ZodNumber;
96
+ medianDays: z.ZodNumber;
97
+ buckets: z.ZodObject<{
98
+ d0_1: z.ZodNumber;
99
+ d2_7: z.ZodNumber;
100
+ d8_30: z.ZodNumber;
101
+ d31_90: z.ZodNumber;
102
+ d90_plus: z.ZodNumber;
103
+ }, "strip", z.ZodTypeAny, {
104
+ d0_1: number;
105
+ d2_7: number;
106
+ d8_30: number;
107
+ d31_90: number;
108
+ d90_plus: number;
109
+ }, {
110
+ d0_1: number;
111
+ d2_7: number;
112
+ d8_30: number;
113
+ d31_90: number;
114
+ d90_plus: number;
115
+ }>;
116
+ }, "strip", z.ZodTypeAny, {
117
+ commitsConsidered: number;
118
+ avgDays: number;
119
+ medianDays: number;
120
+ buckets: {
121
+ d0_1: number;
122
+ d2_7: number;
123
+ d8_30: number;
124
+ d31_90: number;
125
+ d90_plus: number;
126
+ };
127
+ }, {
128
+ commitsConsidered: number;
129
+ avgDays: number;
130
+ medianDays: number;
131
+ buckets: {
132
+ d0_1: number;
133
+ d2_7: number;
134
+ d8_30: number;
135
+ d31_90: number;
136
+ d90_plus: number;
137
+ };
138
+ }>;
139
+ }, "strip", z.ZodTypeAny, {
140
+ mergeRatio: {
141
+ mergeRatio: number;
142
+ commitsTotal: number;
143
+ commitsMerged: number;
144
+ };
145
+ persistence: {
146
+ commitsConsidered: number;
147
+ avgDays: number;
148
+ medianDays: number;
149
+ buckets: {
150
+ d0_1: number;
151
+ d2_7: number;
152
+ d8_30: number;
153
+ d31_90: number;
154
+ d90_plus: number;
155
+ };
156
+ };
157
+ }, {
158
+ mergeRatio: {
159
+ mergeRatio: number;
160
+ commitsTotal: number;
161
+ commitsMerged: number;
162
+ };
163
+ persistence: {
164
+ commitsConsidered: number;
165
+ avgDays: number;
166
+ medianDays: number;
167
+ buckets: {
168
+ d0_1: number;
169
+ d2_7: number;
170
+ d8_30: number;
171
+ d31_90: number;
172
+ d90_plus: number;
173
+ };
174
+ };
175
+ }>;
176
+ type Baseline = z.infer<typeof Baseline>;
177
+ declare const Delta: z.ZodObject<{
178
+ mergeRatio: z.ZodNumber;
179
+ avgPersistenceDays: z.ZodNumber;
180
+ medianPersistenceDays: z.ZodNumber;
181
+ }, "strip", z.ZodTypeAny, {
182
+ mergeRatio: number;
183
+ avgPersistenceDays: number;
184
+ medianPersistenceDays: number;
185
+ }, {
186
+ mergeRatio: number;
187
+ avgPersistenceDays: number;
188
+ medianPersistenceDays: number;
189
+ }>;
190
+ type Delta = z.infer<typeof Delta>;
65
191
  declare const Metrics: z.ZodObject<{
66
192
  generatedAt: z.ZodString;
67
193
  window: z.ZodObject<{
@@ -135,6 +261,116 @@ declare const Metrics: z.ZodObject<{
135
261
  d90_plus: number;
136
262
  };
137
263
  }>;
264
+ baseline: z.ZodObject<{
265
+ mergeRatio: z.ZodObject<{
266
+ commitsTotal: z.ZodNumber;
267
+ commitsMerged: z.ZodNumber;
268
+ mergeRatio: z.ZodNumber;
269
+ }, "strip", z.ZodTypeAny, {
270
+ mergeRatio: number;
271
+ commitsTotal: number;
272
+ commitsMerged: number;
273
+ }, {
274
+ mergeRatio: number;
275
+ commitsTotal: number;
276
+ commitsMerged: number;
277
+ }>;
278
+ persistence: z.ZodObject<{
279
+ commitsConsidered: z.ZodNumber;
280
+ avgDays: z.ZodNumber;
281
+ medianDays: z.ZodNumber;
282
+ buckets: z.ZodObject<{
283
+ d0_1: z.ZodNumber;
284
+ d2_7: z.ZodNumber;
285
+ d8_30: z.ZodNumber;
286
+ d31_90: z.ZodNumber;
287
+ d90_plus: z.ZodNumber;
288
+ }, "strip", z.ZodTypeAny, {
289
+ d0_1: number;
290
+ d2_7: number;
291
+ d8_30: number;
292
+ d31_90: number;
293
+ d90_plus: number;
294
+ }, {
295
+ d0_1: number;
296
+ d2_7: number;
297
+ d8_30: number;
298
+ d31_90: number;
299
+ d90_plus: number;
300
+ }>;
301
+ }, "strip", z.ZodTypeAny, {
302
+ commitsConsidered: number;
303
+ avgDays: number;
304
+ medianDays: number;
305
+ buckets: {
306
+ d0_1: number;
307
+ d2_7: number;
308
+ d8_30: number;
309
+ d31_90: number;
310
+ d90_plus: number;
311
+ };
312
+ }, {
313
+ commitsConsidered: number;
314
+ avgDays: number;
315
+ medianDays: number;
316
+ buckets: {
317
+ d0_1: number;
318
+ d2_7: number;
319
+ d8_30: number;
320
+ d31_90: number;
321
+ d90_plus: number;
322
+ };
323
+ }>;
324
+ }, "strip", z.ZodTypeAny, {
325
+ mergeRatio: {
326
+ mergeRatio: number;
327
+ commitsTotal: number;
328
+ commitsMerged: number;
329
+ };
330
+ persistence: {
331
+ commitsConsidered: number;
332
+ avgDays: number;
333
+ medianDays: number;
334
+ buckets: {
335
+ d0_1: number;
336
+ d2_7: number;
337
+ d8_30: number;
338
+ d31_90: number;
339
+ d90_plus: number;
340
+ };
341
+ };
342
+ }, {
343
+ mergeRatio: {
344
+ mergeRatio: number;
345
+ commitsTotal: number;
346
+ commitsMerged: number;
347
+ };
348
+ persistence: {
349
+ commitsConsidered: number;
350
+ avgDays: number;
351
+ medianDays: number;
352
+ buckets: {
353
+ d0_1: number;
354
+ d2_7: number;
355
+ d8_30: number;
356
+ d31_90: number;
357
+ d90_plus: number;
358
+ };
359
+ };
360
+ }>;
361
+ delta: z.ZodObject<{
362
+ mergeRatio: z.ZodNumber;
363
+ avgPersistenceDays: z.ZodNumber;
364
+ medianPersistenceDays: z.ZodNumber;
365
+ }, "strip", z.ZodTypeAny, {
366
+ mergeRatio: number;
367
+ avgPersistenceDays: number;
368
+ medianPersistenceDays: number;
369
+ }, {
370
+ mergeRatio: number;
371
+ avgPersistenceDays: number;
372
+ medianPersistenceDays: number;
373
+ }>;
138
374
  caveats: z.ZodArray<z.ZodString, "many">;
139
375
  }, "strip", z.ZodTypeAny, {
140
376
  generatedAt: string;
@@ -161,6 +397,30 @@ declare const Metrics: z.ZodObject<{
161
397
  d90_plus: number;
162
398
  };
163
399
  };
400
+ baseline: {
401
+ mergeRatio: {
402
+ mergeRatio: number;
403
+ commitsTotal: number;
404
+ commitsMerged: number;
405
+ };
406
+ persistence: {
407
+ commitsConsidered: number;
408
+ avgDays: number;
409
+ medianDays: number;
410
+ buckets: {
411
+ d0_1: number;
412
+ d2_7: number;
413
+ d8_30: number;
414
+ d31_90: number;
415
+ d90_plus: number;
416
+ };
417
+ };
418
+ };
419
+ delta: {
420
+ mergeRatio: number;
421
+ avgPersistenceDays: number;
422
+ medianPersistenceDays: number;
423
+ };
164
424
  caveats: string[];
165
425
  }, {
166
426
  generatedAt: string;
@@ -187,14 +447,40 @@ declare const Metrics: z.ZodObject<{
187
447
  d90_plus: number;
188
448
  };
189
449
  };
450
+ baseline: {
451
+ mergeRatio: {
452
+ mergeRatio: number;
453
+ commitsTotal: number;
454
+ commitsMerged: number;
455
+ };
456
+ persistence: {
457
+ commitsConsidered: number;
458
+ avgDays: number;
459
+ medianDays: number;
460
+ buckets: {
461
+ d0_1: number;
462
+ d2_7: number;
463
+ d8_30: number;
464
+ d31_90: number;
465
+ d90_plus: number;
466
+ };
467
+ };
468
+ };
469
+ delta: {
470
+ mergeRatio: number;
471
+ avgPersistenceDays: number;
472
+ medianPersistenceDays: number;
473
+ };
190
474
  caveats: string[];
191
475
  }>;
192
476
  type Metrics = z.infer<typeof Metrics>;
193
477
 
194
478
  declare function calculateMergeRatio(commitStream: CommitStream): MergeRatio;
479
+ declare function calculateBaselineMergeRatio(commitStream: CommitStream): CohortMergeRatio;
195
480
 
196
- declare function calculatePersistence(commitStream: CommitStream): Persistence;
481
+ declare function calculatePersistence(commitStream: CommitStream, isTarget?: (commit: Commit) => boolean): Persistence;
482
+ declare function calculateBaselinePersistence(commitStream: CommitStream): Persistence;
197
483
 
198
484
  declare function calculateMetrics(commitStream: CommitStream): Metrics;
199
485
 
200
- export { MergeRatio, Metrics, Persistence, calculateMergeRatio, calculateMetrics, calculatePersistence };
486
+ export { Baseline, CohortMergeRatio, Delta, MergeRatio, Metrics, Persistence, calculateBaselineMergeRatio, calculateBaselinePersistence, calculateMergeRatio, calculateMetrics, calculatePersistence };
package/dist/index.js CHANGED
@@ -2,24 +2,33 @@
2
2
  import { formatISODate } from "@aida-dev/core";
3
3
 
4
4
  // src/merge-ratio.ts
5
+ function computeMergeRatio(commits) {
6
+ const merged = commits.filter((commit) => commit.inDefaultBranchAncestry);
7
+ return {
8
+ commitsTotal: commits.length,
9
+ commitsMerged: merged.length,
10
+ mergeRatio: commits.length > 0 ? merged.length / commits.length : 0
11
+ };
12
+ }
5
13
  function calculateMergeRatio(commitStream) {
6
14
  const aiCommits = commitStream.commits.filter((commit) => commit.tags.ai);
7
- const aiCommitsMerged = aiCommits.filter((commit) => commit.inDefaultBranchAncestry);
8
- const aiCommitsTotal = aiCommits.length;
9
- const aiCommitsMergedCount = aiCommitsMerged.length;
10
- const mergeRatio = aiCommitsTotal > 0 ? aiCommitsMergedCount / aiCommitsTotal : 0;
15
+ const result = computeMergeRatio(aiCommits);
11
16
  return {
12
- aiCommitsTotal,
13
- aiCommitsMerged: aiCommitsMergedCount,
14
- mergeRatio
17
+ aiCommitsTotal: result.commitsTotal,
18
+ aiCommitsMerged: result.commitsMerged,
19
+ mergeRatio: result.mergeRatio
15
20
  };
16
21
  }
22
+ function calculateBaselineMergeRatio(commitStream) {
23
+ const nonAICommits = commitStream.commits.filter((commit) => !commit.tags.ai);
24
+ return computeMergeRatio(nonAICommits);
25
+ }
17
26
 
18
27
  // src/persistence.ts
19
28
  import { daysBetween } from "@aida-dev/core";
20
- function calculatePersistence(commitStream) {
21
- const aiCommits = commitStream.commits.filter((commit) => commit.tags.ai);
22
- if (aiCommits.length === 0) {
29
+ function calculatePersistence(commitStream, isTarget = (commit) => commit.tags.ai) {
30
+ const targetCommits = commitStream.commits.filter(isTarget);
31
+ if (targetCommits.length === 0) {
23
32
  return {
24
33
  commitsConsidered: 0,
25
34
  avgDays: 0,
@@ -38,13 +47,13 @@ function calculatePersistence(commitStream) {
38
47
  (a, b) => new Date(a.authorDate).getTime() - new Date(b.authorDate).getTime()
39
48
  );
40
49
  for (const commit of sortedCommits) {
41
- if (commit.tags.ai) {
50
+ if (isTarget(commit)) {
42
51
  const commitDate = new Date(commit.authorDate);
43
52
  for (const file of commit.stats.files) {
44
53
  if (!fileLifecycles.has(file.path)) {
45
54
  fileLifecycles.set(file.path, {
46
55
  path: file.path,
47
- firstAICommitDate: commitDate,
56
+ firstTargetCommitDate: commitDate,
48
57
  lastSeenDate: commitDate,
49
58
  persistenceDays: 0
50
59
  });
@@ -65,7 +74,7 @@ function calculatePersistence(commitStream) {
65
74
  }
66
75
  const persistenceDays = [];
67
76
  for (const lifecycle of fileLifecycles.values()) {
68
- lifecycle.persistenceDays = daysBetween(lifecycle.firstAICommitDate, lifecycle.lastSeenDate);
77
+ lifecycle.persistenceDays = daysBetween(lifecycle.firstTargetCommitDate, lifecycle.lastSeenDate);
69
78
  persistenceDays.push(lifecycle.persistenceDays);
70
79
  }
71
80
  const avgDays = persistenceDays.length > 0 ? persistenceDays.reduce((sum, days) => sum + days, 0) / persistenceDays.length : 0;
@@ -79,13 +88,16 @@ function calculatePersistence(commitStream) {
79
88
  d90_plus: persistenceDays.filter((days) => days > 90).length
80
89
  };
81
90
  return {
82
- commitsConsidered: aiCommits.length,
91
+ commitsConsidered: targetCommits.length,
83
92
  avgDays: Math.round(avgDays * 100) / 100,
84
93
  // Round to 2 decimal places
85
94
  medianDays: Math.round(medianDays * 100) / 100,
86
95
  buckets
87
96
  };
88
97
  }
98
+ function calculateBaselinePersistence(commitStream) {
99
+ return calculatePersistence(commitStream, (commit) => !commit.tags.ai);
100
+ }
89
101
 
90
102
  // src/schema/metrics.ts
91
103
  import { z } from "zod";
@@ -106,6 +118,20 @@ var Persistence = z.object({
106
118
  d90_plus: z.number().int().nonnegative()
107
119
  })
108
120
  });
121
+ var CohortMergeRatio = z.object({
122
+ commitsTotal: z.number().int().nonnegative(),
123
+ commitsMerged: z.number().int().nonnegative(),
124
+ mergeRatio: z.number().min(0).max(1)
125
+ });
126
+ var Baseline = z.object({
127
+ mergeRatio: CohortMergeRatio,
128
+ persistence: Persistence
129
+ });
130
+ var Delta = z.object({
131
+ mergeRatio: z.number(),
132
+ avgPersistenceDays: z.number(),
133
+ medianPersistenceDays: z.number()
134
+ });
109
135
  var Metrics = z.object({
110
136
  generatedAt: z.string().datetime(),
111
137
  window: z.object({
@@ -116,17 +142,31 @@ var Metrics = z.object({
116
142
  defaultBranch: z.string(),
117
143
  mergeRatio: MergeRatio,
118
144
  persistence: Persistence,
145
+ baseline: Baseline,
146
+ delta: Delta,
119
147
  caveats: z.array(z.string())
120
148
  });
121
149
 
122
150
  // src/index.ts
151
+ function round(value, decimals) {
152
+ const factor = 10 ** decimals;
153
+ return Math.round(value * factor) / factor;
154
+ }
123
155
  function calculateMetrics(commitStream) {
124
156
  const mergeRatio = calculateMergeRatio(commitStream);
125
157
  const persistence = calculatePersistence(commitStream);
158
+ const baselineMergeRatio = calculateBaselineMergeRatio(commitStream);
159
+ const baselinePersistence = calculateBaselinePersistence(commitStream);
160
+ const delta = {
161
+ mergeRatio: round(mergeRatio.mergeRatio - baselineMergeRatio.mergeRatio, 4),
162
+ avgPersistenceDays: round(persistence.avgDays - baselinePersistence.avgDays, 2),
163
+ medianPersistenceDays: round(persistence.medianDays - baselinePersistence.medianDays, 2)
164
+ };
126
165
  const caveats = [
127
166
  "Persistence is file-level, not line-level.",
128
167
  "Merge ratio: commits from all branches checked against default branch ancestry. Squash merges may undercount unmerged commits.",
129
- "AI tagging uses heuristic patterns; false positives/negatives possible."
168
+ "AI tagging uses heuristic patterns; false positives/negatives possible.",
169
+ "Baseline covers all non-AI-tagged commits; undetected AI usage may leak into the baseline."
130
170
  ];
131
171
  return {
132
172
  generatedAt: formatISODate(/* @__PURE__ */ new Date()),
@@ -138,13 +178,23 @@ function calculateMetrics(commitStream) {
138
178
  defaultBranch: commitStream.defaultBranch,
139
179
  mergeRatio,
140
180
  persistence,
181
+ baseline: {
182
+ mergeRatio: baselineMergeRatio,
183
+ persistence: baselinePersistence
184
+ },
185
+ delta,
141
186
  caveats
142
187
  };
143
188
  }
144
189
  export {
190
+ Baseline,
191
+ CohortMergeRatio,
192
+ Delta,
145
193
  MergeRatio,
146
194
  Metrics,
147
195
  Persistence,
196
+ calculateBaselineMergeRatio,
197
+ calculateBaselinePersistence,
148
198
  calculateMergeRatio,
149
199
  calculateMetrics,
150
200
  calculatePersistence
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/merge-ratio.ts","../src/persistence.ts","../src/schema/metrics.ts"],"sourcesContent":["import { CommitStream, formatISODate } from '@aida-dev/core';\nimport { calculateMergeRatio } from './merge-ratio.js';\nimport { calculatePersistence } from './persistence.js';\nimport { Metrics } from './schema/metrics.js';\n\nexport * from './schema/metrics.js';\nexport * from './merge-ratio.js';\nexport * from './persistence.js';\n\nexport function calculateMetrics(commitStream: CommitStream): Metrics {\n const mergeRatio = calculateMergeRatio(commitStream);\n const persistence = calculatePersistence(commitStream);\n\n const caveats = [\n 'Persistence is file-level, not line-level.',\n 'Merge ratio: commits from all branches checked against default branch ancestry. Squash merges may undercount unmerged commits.',\n 'AI tagging uses heuristic patterns; false positives/negatives possible.',\n ];\n\n return {\n generatedAt: formatISODate(new Date()),\n window: {\n since: commitStream.since,\n until: commitStream.until,\n },\n repoPath: commitStream.repoPath,\n defaultBranch: commitStream.defaultBranch,\n mergeRatio,\n persistence,\n caveats,\n };\n}\n","import { CommitStream } from '@aida-dev/core';\nimport { MergeRatio } from './schema/metrics.js';\n\nexport function calculateMergeRatio(commitStream: CommitStream): MergeRatio {\n const aiCommits = commitStream.commits.filter((commit) => commit.tags.ai);\n const aiCommitsMerged = aiCommits.filter((commit) => commit.inDefaultBranchAncestry);\n\n const aiCommitsTotal = aiCommits.length;\n const aiCommitsMergedCount = aiCommitsMerged.length;\n\n // For MVP, since we're only scanning default branch, merged count equals total\n const mergeRatio = aiCommitsTotal > 0 ? aiCommitsMergedCount / aiCommitsTotal : 0;\n\n return {\n aiCommitsTotal,\n aiCommitsMerged: aiCommitsMergedCount,\n mergeRatio,\n };\n}\n","import { CommitStream, daysBetween } from '@aida-dev/core';\nimport { Persistence } from './schema/metrics.js';\n\ninterface FileLifecycle {\n path: string;\n firstAICommitDate: Date;\n lastSeenDate: Date;\n persistenceDays: number;\n}\n\nexport function calculatePersistence(commitStream: CommitStream): Persistence {\n const aiCommits = commitStream.commits.filter((commit) => commit.tags.ai);\n\n if (aiCommits.length === 0) {\n return {\n commitsConsidered: 0,\n avgDays: 0,\n medianDays: 0,\n buckets: {\n d0_1: 0,\n d2_7: 0,\n d8_30: 0,\n d31_90: 0,\n d90_plus: 0,\n },\n };\n }\n\n // Group files by path and track their lifecycle\n const fileLifecycles = new Map<string, FileLifecycle>();\n\n // Sort commits by date (oldest first)\n const sortedCommits = [...commitStream.commits].sort(\n (a, b) => new Date(a.authorDate).getTime() - new Date(b.authorDate).getTime()\n );\n\n // Track first AI commit per file\n for (const commit of sortedCommits) {\n if (commit.tags.ai) {\n const commitDate = new Date(commit.authorDate);\n\n for (const file of commit.stats.files) {\n if (!fileLifecycles.has(file.path)) {\n fileLifecycles.set(file.path, {\n path: file.path,\n firstAICommitDate: commitDate,\n lastSeenDate: commitDate,\n persistenceDays: 0,\n });\n }\n }\n }\n }\n\n // Track last seen date for each file\n for (const commit of sortedCommits) {\n const commitDate = new Date(commit.authorDate);\n\n for (const file of commit.stats.files) {\n const lifecycle = fileLifecycles.get(file.path);\n if (lifecycle) {\n // Update last seen date if file is not deleted\n if (file.status !== 'deleted') {\n lifecycle.lastSeenDate = commitDate;\n }\n }\n }\n }\n\n // Calculate persistence days for each file\n const persistenceDays: number[] = [];\n\n for (const lifecycle of fileLifecycles.values()) {\n lifecycle.persistenceDays = daysBetween(lifecycle.firstAICommitDate, lifecycle.lastSeenDate);\n persistenceDays.push(lifecycle.persistenceDays);\n }\n\n // Calculate statistics\n const avgDays =\n persistenceDays.length > 0\n ? persistenceDays.reduce((sum, days) => sum + days, 0) / persistenceDays.length\n : 0;\n\n const sortedDays = [...persistenceDays].sort((a, b) => a - b);\n const medianDays =\n sortedDays.length > 0\n ? sortedDays.length % 2 === 0\n ? (sortedDays[sortedDays.length / 2 - 1] + sortedDays[sortedDays.length / 2]) / 2\n : sortedDays[Math.floor(sortedDays.length / 2)]\n : 0;\n\n // Calculate buckets\n const buckets = {\n d0_1: persistenceDays.filter((days) => days <= 1).length,\n d2_7: persistenceDays.filter((days) => days >= 2 && days <= 7).length,\n d8_30: persistenceDays.filter((days) => days >= 8 && days <= 30).length,\n d31_90: persistenceDays.filter((days) => days >= 31 && days <= 90).length,\n d90_plus: persistenceDays.filter((days) => days > 90).length,\n };\n\n return {\n commitsConsidered: aiCommits.length,\n avgDays: Math.round(avgDays * 100) / 100, // Round to 2 decimal places\n medianDays: Math.round(medianDays * 100) / 100,\n buckets,\n };\n}\n","import { z } from 'zod';\n\nexport const MergeRatio = z.object({\n aiCommitsTotal: z.number().int().nonnegative(),\n aiCommitsMerged: z.number().int().nonnegative(),\n mergeRatio: z.number().min(0).max(1),\n});\n\nexport const Persistence = z.object({\n commitsConsidered: z.number().int().nonnegative(),\n avgDays: z.number().nonnegative(),\n medianDays: z.number().nonnegative(),\n buckets: z.object({\n d0_1: z.number().int().nonnegative(),\n d2_7: z.number().int().nonnegative(),\n d8_30: z.number().int().nonnegative(),\n d31_90: z.number().int().nonnegative(),\n d90_plus: z.number().int().nonnegative(),\n }),\n});\n\nexport const Metrics = z.object({\n generatedAt: z.string().datetime(),\n window: z.object({\n since: z.string().optional(),\n until: z.string().optional(),\n }),\n repoPath: z.string(),\n defaultBranch: z.string(),\n mergeRatio: MergeRatio,\n persistence: Persistence,\n caveats: z.array(z.string()),\n});\n\nexport type MergeRatio = z.infer<typeof MergeRatio>;\nexport type Persistence = z.infer<typeof Persistence>;\nexport type Metrics = z.infer<typeof Metrics>;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/merge-ratio.ts","../src/persistence.ts","../src/schema/metrics.ts"],"sourcesContent":["import { CommitStream, formatISODate } from '@aida-dev/core';\nimport { calculateBaselineMergeRatio, calculateMergeRatio } from './merge-ratio.js';\nimport { calculateBaselinePersistence, calculatePersistence } from './persistence.js';\nimport { Metrics } from './schema/metrics.js';\n\nexport * from './schema/metrics.js';\nexport * from './merge-ratio.js';\nexport * from './persistence.js';\n\nfunction round(value: number, decimals: number): number {\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n}\n\nexport function calculateMetrics(commitStream: CommitStream): Metrics {\n const mergeRatio = calculateMergeRatio(commitStream);\n const persistence = calculatePersistence(commitStream);\n const baselineMergeRatio = calculateBaselineMergeRatio(commitStream);\n const baselinePersistence = calculateBaselinePersistence(commitStream);\n\n const delta = {\n mergeRatio: round(mergeRatio.mergeRatio - baselineMergeRatio.mergeRatio, 4),\n avgPersistenceDays: round(persistence.avgDays - baselinePersistence.avgDays, 2),\n medianPersistenceDays: round(persistence.medianDays - baselinePersistence.medianDays, 2),\n };\n\n const caveats = [\n 'Persistence is file-level, not line-level.',\n 'Merge ratio: commits from all branches checked against default branch ancestry. Squash merges may undercount unmerged commits.',\n 'AI tagging uses heuristic patterns; false positives/negatives possible.',\n 'Baseline covers all non-AI-tagged commits; undetected AI usage may leak into the baseline.',\n ];\n\n return {\n generatedAt: formatISODate(new Date()),\n window: {\n since: commitStream.since,\n until: commitStream.until,\n },\n repoPath: commitStream.repoPath,\n defaultBranch: commitStream.defaultBranch,\n mergeRatio,\n persistence,\n baseline: {\n mergeRatio: baselineMergeRatio,\n persistence: baselinePersistence,\n },\n delta,\n caveats,\n };\n}\n","import { Commit, CommitStream } from '@aida-dev/core';\nimport { CohortMergeRatio, MergeRatio } from './schema/metrics.js';\n\nfunction computeMergeRatio(commits: Commit[]): CohortMergeRatio {\n const merged = commits.filter((commit) => commit.inDefaultBranchAncestry);\n\n return {\n commitsTotal: commits.length,\n commitsMerged: merged.length,\n mergeRatio: commits.length > 0 ? merged.length / commits.length : 0,\n };\n}\n\nexport function calculateMergeRatio(commitStream: CommitStream): MergeRatio {\n const aiCommits = commitStream.commits.filter((commit) => commit.tags.ai);\n const result = computeMergeRatio(aiCommits);\n\n return {\n aiCommitsTotal: result.commitsTotal,\n aiCommitsMerged: result.commitsMerged,\n mergeRatio: result.mergeRatio,\n };\n}\n\nexport function calculateBaselineMergeRatio(commitStream: CommitStream): CohortMergeRatio {\n const nonAICommits = commitStream.commits.filter((commit) => !commit.tags.ai);\n return computeMergeRatio(nonAICommits);\n}\n","import { Commit, CommitStream, daysBetween } from '@aida-dev/core';\nimport { Persistence } from './schema/metrics.js';\n\ninterface FileLifecycle {\n path: string;\n firstTargetCommitDate: Date;\n lastSeenDate: Date;\n persistenceDays: number;\n}\n\nexport function calculatePersistence(\n commitStream: CommitStream,\n isTarget: (commit: Commit) => boolean = (commit) => commit.tags.ai\n): Persistence {\n const targetCommits = commitStream.commits.filter(isTarget);\n\n if (targetCommits.length === 0) {\n return {\n commitsConsidered: 0,\n avgDays: 0,\n medianDays: 0,\n buckets: {\n d0_1: 0,\n d2_7: 0,\n d8_30: 0,\n d31_90: 0,\n d90_plus: 0,\n },\n };\n }\n\n // Group files by path and track their lifecycle\n const fileLifecycles = new Map<string, FileLifecycle>();\n\n // Sort commits by date (oldest first)\n const sortedCommits = [...commitStream.commits].sort(\n (a, b) => new Date(a.authorDate).getTime() - new Date(b.authorDate).getTime()\n );\n\n // Track first target commit per file\n for (const commit of sortedCommits) {\n if (isTarget(commit)) {\n const commitDate = new Date(commit.authorDate);\n\n for (const file of commit.stats.files) {\n if (!fileLifecycles.has(file.path)) {\n fileLifecycles.set(file.path, {\n path: file.path,\n firstTargetCommitDate: commitDate,\n lastSeenDate: commitDate,\n persistenceDays: 0,\n });\n }\n }\n }\n }\n\n // Track last seen date for each file\n for (const commit of sortedCommits) {\n const commitDate = new Date(commit.authorDate);\n\n for (const file of commit.stats.files) {\n const lifecycle = fileLifecycles.get(file.path);\n if (lifecycle) {\n // Update last seen date if file is not deleted\n if (file.status !== 'deleted') {\n lifecycle.lastSeenDate = commitDate;\n }\n }\n }\n }\n\n // Calculate persistence days for each file\n const persistenceDays: number[] = [];\n\n for (const lifecycle of fileLifecycles.values()) {\n lifecycle.persistenceDays = daysBetween(lifecycle.firstTargetCommitDate, lifecycle.lastSeenDate);\n persistenceDays.push(lifecycle.persistenceDays);\n }\n\n // Calculate statistics\n const avgDays =\n persistenceDays.length > 0\n ? persistenceDays.reduce((sum, days) => sum + days, 0) / persistenceDays.length\n : 0;\n\n const sortedDays = [...persistenceDays].sort((a, b) => a - b);\n const medianDays =\n sortedDays.length > 0\n ? sortedDays.length % 2 === 0\n ? (sortedDays[sortedDays.length / 2 - 1] + sortedDays[sortedDays.length / 2]) / 2\n : sortedDays[Math.floor(sortedDays.length / 2)]\n : 0;\n\n // Calculate buckets\n const buckets = {\n d0_1: persistenceDays.filter((days) => days <= 1).length,\n d2_7: persistenceDays.filter((days) => days >= 2 && days <= 7).length,\n d8_30: persistenceDays.filter((days) => days >= 8 && days <= 30).length,\n d31_90: persistenceDays.filter((days) => days >= 31 && days <= 90).length,\n d90_plus: persistenceDays.filter((days) => days > 90).length,\n };\n\n return {\n commitsConsidered: targetCommits.length,\n avgDays: Math.round(avgDays * 100) / 100, // Round to 2 decimal places\n medianDays: Math.round(medianDays * 100) / 100,\n buckets,\n };\n}\n\nexport function calculateBaselinePersistence(commitStream: CommitStream): Persistence {\n return calculatePersistence(commitStream, (commit) => !commit.tags.ai);\n}\n","import { z } from 'zod';\n\nexport const MergeRatio = z.object({\n aiCommitsTotal: z.number().int().nonnegative(),\n aiCommitsMerged: z.number().int().nonnegative(),\n mergeRatio: z.number().min(0).max(1),\n});\n\nexport const Persistence = z.object({\n commitsConsidered: z.number().int().nonnegative(),\n avgDays: z.number().nonnegative(),\n medianDays: z.number().nonnegative(),\n buckets: z.object({\n d0_1: z.number().int().nonnegative(),\n d2_7: z.number().int().nonnegative(),\n d8_30: z.number().int().nonnegative(),\n d31_90: z.number().int().nonnegative(),\n d90_plus: z.number().int().nonnegative(),\n }),\n});\n\nexport const CohortMergeRatio = z.object({\n commitsTotal: z.number().int().nonnegative(),\n commitsMerged: z.number().int().nonnegative(),\n mergeRatio: z.number().min(0).max(1),\n});\n\nexport const Baseline = z.object({\n mergeRatio: CohortMergeRatio,\n persistence: Persistence,\n});\n\nexport const Delta = z.object({\n mergeRatio: z.number(),\n avgPersistenceDays: z.number(),\n medianPersistenceDays: z.number(),\n});\n\nexport const Metrics = z.object({\n generatedAt: z.string().datetime(),\n window: z.object({\n since: z.string().optional(),\n until: z.string().optional(),\n }),\n repoPath: z.string(),\n defaultBranch: z.string(),\n mergeRatio: MergeRatio,\n persistence: Persistence,\n baseline: Baseline,\n delta: Delta,\n caveats: z.array(z.string()),\n});\n\nexport type MergeRatio = z.infer<typeof MergeRatio>;\nexport type Persistence = z.infer<typeof Persistence>;\nexport type CohortMergeRatio = z.infer<typeof CohortMergeRatio>;\nexport type Baseline = z.infer<typeof Baseline>;\nexport type Delta = z.infer<typeof Delta>;\nexport type Metrics = z.infer<typeof Metrics>;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@aida-dev/metrics",
3
- "version": "0.1.7",
3
+ "version": "0.3.0",
4
+ "description": "Metrics engine for AIDA (AI Development Accounting) - Merge ratio, persistence, and AI impact analysis",
4
5
  "type": "module",
5
6
  "main": "dist/index.js",
6
7
  "module": "dist/index.js",
@@ -10,7 +11,7 @@
10
11
  ],
11
12
  "dependencies": {
12
13
  "zod": "^3.22.4",
13
- "@aida-dev/core": "0.6.0"
14
+ "@aida-dev/core": "0.7.0"
14
15
  },
15
16
  "devDependencies": {
16
17
  "tsup": "^8.0.0",
@@ -20,6 +21,27 @@
20
21
  "@types/node": "^20.0.0",
21
22
  "@vitest/coverage-v8": "^2.0.0"
22
23
  },
24
+ "keywords": [
25
+ "ai",
26
+ "development",
27
+ "metrics",
28
+ "git",
29
+ "analysis"
30
+ ],
31
+ "author": "Francesco Falanga <falanga.fra@gmail.com>",
32
+ "license": "MIT",
33
+ "homepage": "https://github.com/ceccode/aida-metrics#readme",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/ceccode/aida-metrics.git",
37
+ "directory": "packages/metrics"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/ceccode/aida-metrics/issues"
41
+ },
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ },
23
45
  "publishConfig": {
24
46
  "access": "public"
25
47
  },