@mneme-ai/core 0.11.1 → 0.13.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 (77) hide show
  1. package/dist/insights/chronicle.d.ts +41 -0
  2. package/dist/insights/chronicle.d.ts.map +1 -0
  3. package/dist/insights/chronicle.js +169 -0
  4. package/dist/insights/chronicle.js.map +1 -0
  5. package/dist/insights/chronicle.test.d.ts +2 -0
  6. package/dist/insights/chronicle.test.d.ts.map +1 -0
  7. package/dist/insights/chronicle.test.js +92 -0
  8. package/dist/insights/chronicle.test.js.map +1 -0
  9. package/dist/insights/cluster.d.ts +52 -0
  10. package/dist/insights/cluster.d.ts.map +1 -0
  11. package/dist/insights/cluster.js +154 -0
  12. package/dist/insights/cluster.js.map +1 -0
  13. package/dist/insights/cluster.test.d.ts +2 -0
  14. package/dist/insights/cluster.test.d.ts.map +1 -0
  15. package/dist/insights/cluster.test.js +106 -0
  16. package/dist/insights/cluster.test.js.map +1 -0
  17. package/dist/insights/constellation.d.ts +63 -0
  18. package/dist/insights/constellation.d.ts.map +1 -0
  19. package/dist/insights/constellation.js +147 -0
  20. package/dist/insights/constellation.js.map +1 -0
  21. package/dist/insights/constellation.test.d.ts +2 -0
  22. package/dist/insights/constellation.test.d.ts.map +1 -0
  23. package/dist/insights/constellation.test.js +105 -0
  24. package/dist/insights/constellation.test.js.map +1 -0
  25. package/dist/insights/dna.d.ts +100 -0
  26. package/dist/insights/dna.d.ts.map +1 -0
  27. package/dist/insights/dna.js +264 -0
  28. package/dist/insights/dna.js.map +1 -0
  29. package/dist/insights/dna.test.d.ts +2 -0
  30. package/dist/insights/dna.test.d.ts.map +1 -0
  31. package/dist/insights/dna.test.js +142 -0
  32. package/dist/insights/dna.test.js.map +1 -0
  33. package/dist/insights/drift.d.ts +43 -0
  34. package/dist/insights/drift.d.ts.map +1 -0
  35. package/dist/insights/drift.js +170 -0
  36. package/dist/insights/drift.js.map +1 -0
  37. package/dist/insights/drift.test.d.ts +2 -0
  38. package/dist/insights/drift.test.d.ts.map +1 -0
  39. package/dist/insights/drift.test.js +126 -0
  40. package/dist/insights/drift.test.js.map +1 -0
  41. package/dist/insights/export-bundle.d.ts +53 -0
  42. package/dist/insights/export-bundle.d.ts.map +1 -0
  43. package/dist/insights/export-bundle.js +156 -0
  44. package/dist/insights/export-bundle.js.map +1 -0
  45. package/dist/insights/export-bundle.test.d.ts +2 -0
  46. package/dist/insights/export-bundle.test.d.ts.map +1 -0
  47. package/dist/insights/export-bundle.test.js +92 -0
  48. package/dist/insights/export-bundle.test.js.map +1 -0
  49. package/dist/insights/index.d.ts +9 -0
  50. package/dist/insights/index.d.ts.map +1 -1
  51. package/dist/insights/index.js +9 -0
  52. package/dist/insights/index.js.map +1 -1
  53. package/dist/insights/manage.d.ts +60 -0
  54. package/dist/insights/manage.d.ts.map +1 -0
  55. package/dist/insights/manage.js +110 -0
  56. package/dist/insights/manage.js.map +1 -0
  57. package/dist/insights/manage.test.d.ts +2 -0
  58. package/dist/insights/manage.test.d.ts.map +1 -0
  59. package/dist/insights/manage.test.js +94 -0
  60. package/dist/insights/manage.test.js.map +1 -0
  61. package/dist/insights/network.d.ts +59 -0
  62. package/dist/insights/network.d.ts.map +1 -0
  63. package/dist/insights/network.js +231 -0
  64. package/dist/insights/network.js.map +1 -0
  65. package/dist/insights/network.test.d.ts +2 -0
  66. package/dist/insights/network.test.d.ts.map +1 -0
  67. package/dist/insights/network.test.js +100 -0
  68. package/dist/insights/network.test.js.map +1 -0
  69. package/dist/insights/oracle.d.ts +59 -0
  70. package/dist/insights/oracle.d.ts.map +1 -0
  71. package/dist/insights/oracle.js +0 -0
  72. package/dist/insights/oracle.js.map +1 -0
  73. package/dist/insights/oracle.test.d.ts +2 -0
  74. package/dist/insights/oracle.test.d.ts.map +1 -0
  75. package/dist/insights/oracle.test.js +133 -0
  76. package/dist/insights/oracle.test.js.map +1 -0
  77. package/package.json +1 -1
@@ -0,0 +1,264 @@
1
+ const CONVENTIONAL_RE = /^(feat|fix|chore|docs|style|refactor|test|perf|build|ci|revert)(\([^)]*\))?:/;
2
+ const IMPERATIVE_FIRST_WORDS = new Set([
3
+ "add", "fix", "update", "remove", "refactor", "improve", "rename", "move",
4
+ "extract", "introduce", "implement", "support", "drop", "use", "make", "ensure",
5
+ "prevent", "handle", "wire", "expose", "switch", "replace", "migrate",
6
+ "polish", "simplify", "consolidate", "split", "delete", "init", "scaffold",
7
+ "bump", "release", "publish", "ship", "build", "configure", "enable", "disable",
8
+ "create", "test", "document", "clarify", "tighten", "guard", "validate",
9
+ ]);
10
+ /** Build a Codebase DNA strand for the given author from commits they made. */
11
+ export function extractDna(commits, author, opts = {}) {
12
+ const filtered = commits.filter((c) => c.authorEmail.toLowerCase() === author.toLowerCase() ||
13
+ c.authorName.toLowerCase() === author.toLowerCase());
14
+ if (filtered.length === 0) {
15
+ return emptyDna(author);
16
+ }
17
+ const sorted = [...filtered].sort((a, b) => a.authorDate.localeCompare(b.authorDate));
18
+ const fromDate = sorted[0].authorDate.slice(0, 10);
19
+ const toDate = sorted[sorted.length - 1].authorDate.slice(0, 10);
20
+ const style = computeStyle(sorted);
21
+ const message = computeMessage(sorted);
22
+ const hours = computeHours(sorted);
23
+ const files = computeFiles(sorted);
24
+ const dna = {
25
+ author,
26
+ commitCount: sorted.length,
27
+ fromDate,
28
+ toDate,
29
+ style,
30
+ message,
31
+ hours,
32
+ files,
33
+ hash: "", // filled in below
34
+ };
35
+ dna.hash = stableHash(dna);
36
+ return dna;
37
+ }
38
+ /** Compatibility score 0..1 between two DNA strands. */
39
+ export function compareDna(a, b) {
40
+ const axes = [];
41
+ axes.push({ axis: "style", similarity: styleSim(a.style, b.style) });
42
+ axes.push({ axis: "message", similarity: messageSim(a.message, b.message) });
43
+ axes.push({ axis: "hours", similarity: hoursSim(a.hours, b.hours) });
44
+ axes.push({ axis: "files", similarity: filesSim(a.files, b.files) });
45
+ const overall = axes.reduce((s, x) => s + x.similarity, 0) / Math.max(1, axes.length);
46
+ return {
47
+ similarity: Number(overall.toFixed(3)),
48
+ axes: axes.map((a) => ({ axis: a.axis, similarity: Number(a.similarity.toFixed(3)) })),
49
+ };
50
+ }
51
+ // ─── computation ───────────────────────────────────────────────────────
52
+ function computeStyle(cs) {
53
+ const filesPer = median(cs.map((c) => c.files.length));
54
+ let testHits = 0;
55
+ let issueHits = 0;
56
+ let convHits = 0;
57
+ for (const c of cs) {
58
+ if (c.files.some((f) => /\b(test|spec|__tests__)\b|\.test\.|\.spec\./.test(f))) {
59
+ testHits++;
60
+ }
61
+ if (c.issueRefs?.length || c.prNumber)
62
+ issueHits++;
63
+ if (CONVENTIONAL_RE.test(c.subject))
64
+ convHits++;
65
+ }
66
+ return {
67
+ filesPerCommit: filesPer,
68
+ churnPerCommit: 0, // cheap default — caller can pass changes if needed
69
+ testRatio: cs.length === 0 ? 0 : testHits / cs.length,
70
+ issueRefRatio: cs.length === 0 ? 0 : issueHits / cs.length,
71
+ conventionalRatio: cs.length === 0 ? 0 : convHits / cs.length,
72
+ };
73
+ }
74
+ function computeMessage(cs) {
75
+ let totalLen = 0;
76
+ let imp = 0;
77
+ let body = 0;
78
+ const verbs = new Map();
79
+ for (const c of cs) {
80
+ const subj = c.subject.trim();
81
+ totalLen += subj.length;
82
+ if (c.body && c.body.trim().length > 0)
83
+ body++;
84
+ // strip conventional prefix
85
+ const cleaned = subj.replace(CONVENTIONAL_RE, "").trim();
86
+ const firstWord = (cleaned.match(/^[A-Za-z]+/)?.[0] || "").toLowerCase();
87
+ if (IMPERATIVE_FIRST_WORDS.has(firstWord))
88
+ imp++;
89
+ if (firstWord)
90
+ verbs.set(firstWord, (verbs.get(firstWord) ?? 0) + 1);
91
+ }
92
+ const top = [...verbs.entries()]
93
+ .sort((a, b) => b[1] - a[1])
94
+ .slice(0, 5)
95
+ .map(([verb, count]) => ({ verb, count }));
96
+ return {
97
+ avgSubjectLength: cs.length === 0 ? 0 : Math.round(totalLen / cs.length),
98
+ imperativeRatio: cs.length === 0 ? 0 : imp / cs.length,
99
+ bodyRatio: cs.length === 0 ? 0 : body / cs.length,
100
+ topVerbs: top,
101
+ };
102
+ }
103
+ function computeHours(cs) {
104
+ const byHour = new Array(24).fill(0);
105
+ const byWeekday = new Array(7).fill(0);
106
+ let weekend = 0;
107
+ for (const c of cs) {
108
+ const d = new Date(c.authorDate);
109
+ if (Number.isNaN(d.getTime()))
110
+ continue;
111
+ byHour[d.getUTCHours()] = (byHour[d.getUTCHours()] ?? 0) + 1;
112
+ const w = d.getUTCDay();
113
+ byWeekday[w] = (byWeekday[w] ?? 0) + 1;
114
+ if (w === 0 || w === 6)
115
+ weekend++;
116
+ }
117
+ // peak window = 4-hour band with highest sum
118
+ let bestStart = 0;
119
+ let bestSum = -1;
120
+ for (let i = 0; i < 24; i++) {
121
+ let s = 0;
122
+ for (let k = 0; k < 4; k++)
123
+ s += byHour[(i + k) % 24] ?? 0;
124
+ if (s > bestSum) {
125
+ bestSum = s;
126
+ bestStart = i;
127
+ }
128
+ }
129
+ const peak = `${pad2(bestStart)}:00–${pad2((bestStart + 4) % 24)}:00`;
130
+ return {
131
+ byHour,
132
+ byWeekday,
133
+ weekendRatio: cs.length === 0 ? 0 : weekend / cs.length,
134
+ peakWindow: peak,
135
+ };
136
+ }
137
+ function computeFiles(cs) {
138
+ const dirCounts = new Map();
139
+ const extCounts = new Map();
140
+ let totalFiles = 0;
141
+ for (const c of cs) {
142
+ for (const f of c.files) {
143
+ totalFiles++;
144
+ const dir = f.split("/").slice(0, 2).join("/") || "(root)";
145
+ dirCounts.set(dir, (dirCounts.get(dir) ?? 0) + 1);
146
+ const ext = (f.match(/\.[A-Za-z0-9]+$/)?.[0] || "(none)").toLowerCase();
147
+ extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);
148
+ }
149
+ }
150
+ const topDirs = [...dirCounts.entries()]
151
+ .sort((a, b) => b[1] - a[1])
152
+ .slice(0, 5)
153
+ .map(([dir, n]) => ({ dir, share: totalFiles === 0 ? 0 : n / totalFiles }));
154
+ const topExts = [...extCounts.entries()]
155
+ .sort((a, b) => b[1] - a[1])
156
+ .slice(0, 5)
157
+ .map(([ext, n]) => ({ ext, share: totalFiles === 0 ? 0 : n / totalFiles }));
158
+ return { topDirs, topExts };
159
+ }
160
+ // ─── similarity helpers ────────────────────────────────────────────────
161
+ function styleSim(a, b) {
162
+ const axes = [
163
+ 1 - clamp(Math.abs(a.filesPerCommit - b.filesPerCommit) / 10),
164
+ 1 - clamp(Math.abs(a.testRatio - b.testRatio)),
165
+ 1 - clamp(Math.abs(a.issueRefRatio - b.issueRefRatio)),
166
+ 1 - clamp(Math.abs(a.conventionalRatio - b.conventionalRatio)),
167
+ ];
168
+ return mean(axes);
169
+ }
170
+ function messageSim(a, b) {
171
+ const lenSim = 1 - clamp(Math.abs(a.avgSubjectLength - b.avgSubjectLength) / 80);
172
+ const impSim = 1 - clamp(Math.abs(a.imperativeRatio - b.imperativeRatio));
173
+ const bodySim = 1 - clamp(Math.abs(a.bodyRatio - b.bodyRatio));
174
+ const verbSim = jaccard(new Set(a.topVerbs.map((v) => v.verb)), new Set(b.topVerbs.map((v) => v.verb)));
175
+ return mean([lenSim, impSim, bodySim, verbSim]);
176
+ }
177
+ function hoursSim(a, b) {
178
+ return cosineSimArr(normalize(a.byHour), normalize(b.byHour));
179
+ }
180
+ function filesSim(a, b) {
181
+ return jaccard(new Set(a.topDirs.map((d) => d.dir)), new Set(b.topDirs.map((d) => d.dir)));
182
+ }
183
+ function jaccard(a, b) {
184
+ if (a.size === 0 && b.size === 0)
185
+ return 1;
186
+ let inter = 0;
187
+ for (const x of a)
188
+ if (b.has(x))
189
+ inter++;
190
+ const union = a.size + b.size - inter;
191
+ return union === 0 ? 0 : inter / union;
192
+ }
193
+ function cosineSimArr(a, b) {
194
+ let dot = 0;
195
+ let na = 0;
196
+ let nb = 0;
197
+ const n = Math.min(a.length, b.length);
198
+ for (let i = 0; i < n; i++) {
199
+ const ai = a[i] ?? 0;
200
+ const bi = b[i] ?? 0;
201
+ dot += ai * bi;
202
+ na += ai * ai;
203
+ nb += bi * bi;
204
+ }
205
+ const denom = Math.sqrt(na) * Math.sqrt(nb);
206
+ return denom === 0 ? 0 : dot / denom;
207
+ }
208
+ function normalize(xs) {
209
+ const sum = xs.reduce((s, x) => s + x, 0);
210
+ if (sum === 0)
211
+ return xs.slice();
212
+ return xs.map((x) => x / sum);
213
+ }
214
+ function clamp(v) {
215
+ if (v < 0)
216
+ return 0;
217
+ if (v > 1)
218
+ return 1;
219
+ return v;
220
+ }
221
+ function mean(xs) {
222
+ if (xs.length === 0)
223
+ return 0;
224
+ return xs.reduce((s, x) => s + x, 0) / xs.length;
225
+ }
226
+ function median(xs) {
227
+ if (xs.length === 0)
228
+ return 0;
229
+ const s = [...xs].sort((a, b) => a - b);
230
+ const m = Math.floor(s.length / 2);
231
+ return s.length % 2 === 1 ? s[m] : (s[m - 1] + s[m]) / 2;
232
+ }
233
+ function pad2(n) {
234
+ return n < 10 ? "0" + n : "" + n;
235
+ }
236
+ function emptyDna(author) {
237
+ return {
238
+ author,
239
+ commitCount: 0,
240
+ fromDate: "",
241
+ toDate: "",
242
+ style: { filesPerCommit: 0, churnPerCommit: 0, testRatio: 0, issueRefRatio: 0, conventionalRatio: 0 },
243
+ message: { avgSubjectLength: 0, imperativeRatio: 0, bodyRatio: 0, topVerbs: [] },
244
+ hours: { byHour: new Array(24).fill(0), byWeekday: new Array(7).fill(0), weekendRatio: 0, peakWindow: "00:00–00:00" },
245
+ files: { topDirs: [], topExts: [] },
246
+ hash: "0000000",
247
+ };
248
+ }
249
+ function stableHash(dna) {
250
+ // FNV-1a 32-bit hash over a canonical string representation
251
+ const json = JSON.stringify({
252
+ author: dna.author,
253
+ style: dna.style,
254
+ message: { ...dna.message, topVerbs: dna.message.topVerbs.map((v) => v.verb) },
255
+ files: { topDirs: dna.files.topDirs.map((d) => d.dir), topExts: dna.files.topExts.map((e) => e.ext) },
256
+ });
257
+ let h = 0x811c9dc5;
258
+ for (let i = 0; i < json.length; i++) {
259
+ h ^= json.charCodeAt(i);
260
+ h = Math.imul(h, 0x01000193);
261
+ }
262
+ return (h >>> 0).toString(16).padStart(8, "0").slice(0, 7);
263
+ }
264
+ //# sourceMappingURL=dna.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dna.js","sourceRoot":"","sources":["../../src/insights/dna.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dna.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dna.test.d.ts","sourceRoot":"","sources":["../../src/insights/dna.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,142 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { extractDna, compareDna } from "./dna.js";
3
+ function mk(p) {
4
+ return {
5
+ hash: p.hash,
6
+ shortHash: p.hash.slice(0, 7),
7
+ authorName: p.author ?? "Alice",
8
+ authorEmail: p.email ?? "alice@example.com",
9
+ authorDate: p.date,
10
+ committerDate: p.date,
11
+ subject: p.subject,
12
+ body: p.body ?? "",
13
+ files: p.files ?? ["src/x.ts"],
14
+ parents: [],
15
+ prNumber: p.pr,
16
+ };
17
+ }
18
+ describe("extractDna", () => {
19
+ it("returns empty strand when no commits match author", () => {
20
+ const dna = extractDna([], "alice@example.com");
21
+ expect(dna.commitCount).toBe(0);
22
+ expect(dna.hash).toBe("0000000");
23
+ });
24
+ it("extracts commitCount and date range correctly", () => {
25
+ const commits = [
26
+ mk({ hash: "a1", date: "2024-01-15T09:00:00Z", subject: "init" }),
27
+ mk({ hash: "a2", date: "2024-06-22T14:00:00Z", subject: "polish" }),
28
+ ];
29
+ const dna = extractDna(commits, "alice@example.com");
30
+ expect(dna.commitCount).toBe(2);
31
+ expect(dna.fromDate).toBe("2024-01-15");
32
+ expect(dna.toDate).toBe("2024-06-22");
33
+ });
34
+ it("filters by author email or name", () => {
35
+ const commits = [
36
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "alice work", author: "Alice", email: "alice@x.com" }),
37
+ mk({ hash: "b1", date: "2024-01-02T09:00:00Z", subject: "bob work", author: "Bob", email: "bob@x.com" }),
38
+ ];
39
+ const aliceDna = extractDna(commits, "alice@x.com");
40
+ expect(aliceDna.commitCount).toBe(1);
41
+ const bobDna = extractDna(commits, "Bob");
42
+ expect(bobDna.commitCount).toBe(1);
43
+ });
44
+ it("conventionalRatio detects conventional-commit prefixes", () => {
45
+ const commits = [
46
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "feat(core): add caching" }),
47
+ mk({ hash: "a2", date: "2024-01-02T09:00:00Z", subject: "fix: handle null body" }),
48
+ mk({ hash: "a3", date: "2024-01-03T09:00:00Z", subject: "random subject" }),
49
+ ];
50
+ const dna = extractDna(commits, "alice@example.com");
51
+ expect(dna.style.conventionalRatio).toBeCloseTo(2 / 3, 2);
52
+ });
53
+ it("imperativeRatio rises when subjects start with imperatives", () => {
54
+ const commits = [
55
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "Add caching" }),
56
+ mk({ hash: "a2", date: "2024-01-02T09:00:00Z", subject: "fix typo" }),
57
+ mk({ hash: "a3", date: "2024-01-03T09:00:00Z", subject: "Update docs" }),
58
+ ];
59
+ const dna = extractDna(commits, "alice@example.com");
60
+ expect(dna.message.imperativeRatio).toBeGreaterThan(0.6);
61
+ });
62
+ it("bodyRatio counts only commits with non-empty body", () => {
63
+ const commits = [
64
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "A", body: "explains why" }),
65
+ mk({ hash: "a2", date: "2024-01-02T09:00:00Z", subject: "B" }),
66
+ ];
67
+ const dna = extractDna(commits, "alice@example.com");
68
+ expect(dna.message.bodyRatio).toBeCloseTo(0.5, 2);
69
+ });
70
+ it("topVerbs lists most-used leading verbs", () => {
71
+ const commits = [
72
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "add x" }),
73
+ mk({ hash: "a2", date: "2024-01-02T09:00:00Z", subject: "add y" }),
74
+ mk({ hash: "a3", date: "2024-01-03T09:00:00Z", subject: "fix z" }),
75
+ ];
76
+ const dna = extractDna(commits, "alice@example.com");
77
+ expect(dna.message.topVerbs[0]?.verb).toBe("add");
78
+ expect(dna.message.topVerbs[0]?.count).toBe(2);
79
+ });
80
+ it("hours histogram counts each commit by UTC hour", () => {
81
+ const commits = [
82
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "x" }),
83
+ mk({ hash: "a2", date: "2024-01-02T09:30:00Z", subject: "x" }),
84
+ mk({ hash: "a3", date: "2024-01-03T15:00:00Z", subject: "x" }),
85
+ ];
86
+ const dna = extractDna(commits, "alice@example.com");
87
+ expect(dna.hours.byHour[9]).toBe(2);
88
+ expect(dna.hours.byHour[15]).toBe(1);
89
+ });
90
+ it("weekendRatio reflects Sat/Sun commits", () => {
91
+ // 2024-06-15 is Saturday, 2024-06-17 is Monday
92
+ const commits = [
93
+ mk({ hash: "a1", date: "2024-06-15T09:00:00Z", subject: "weekend work" }),
94
+ mk({ hash: "a2", date: "2024-06-17T09:00:00Z", subject: "weekday work" }),
95
+ ];
96
+ const dna = extractDna(commits, "alice@example.com");
97
+ expect(dna.hours.weekendRatio).toBe(0.5);
98
+ });
99
+ it("topDirs reflects most-touched root directories", () => {
100
+ const commits = [
101
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "x", files: ["src/auth/x.ts", "src/auth/y.ts"] }),
102
+ mk({ hash: "a2", date: "2024-01-02T09:00:00Z", subject: "x", files: ["src/payments/z.ts"] }),
103
+ ];
104
+ const dna = extractDna(commits, "alice@example.com");
105
+ const topDir = dna.files.topDirs[0]?.dir;
106
+ expect(topDir).toMatch(/^src\//);
107
+ });
108
+ it("hash is deterministic for the same input", () => {
109
+ const commits = [
110
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "init" }),
111
+ ];
112
+ const a = extractDna(commits, "alice@example.com");
113
+ const b = extractDna(commits, "alice@example.com");
114
+ expect(a.hash).toBe(b.hash);
115
+ expect(a.hash.length).toBe(7);
116
+ });
117
+ it("compareDna returns similarity 1.0 for two identical strands", () => {
118
+ const commits = [
119
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "feat: add caching" }),
120
+ mk({ hash: "a2", date: "2024-01-02T09:00:00Z", subject: "fix: handle null" }),
121
+ ];
122
+ const a = extractDna(commits, "alice@example.com");
123
+ const b = extractDna(commits, "alice@example.com");
124
+ const cmp = compareDna(a, b);
125
+ expect(cmp.similarity).toBeGreaterThan(0.95);
126
+ });
127
+ it("compareDna returns lower similarity for divergent styles", () => {
128
+ const aliceCommits = [
129
+ mk({ hash: "a1", date: "2024-01-01T09:00:00Z", subject: "feat: add x", author: "Alice", email: "a@x.com", files: ["src/auth/a.ts"] }),
130
+ mk({ hash: "a2", date: "2024-01-02T09:00:00Z", subject: "feat: add y", author: "Alice", email: "a@x.com", files: ["src/auth/b.ts"] }),
131
+ ];
132
+ const bobCommits = [
133
+ mk({ hash: "b1", date: "2024-01-01T22:00:00Z", subject: "did some stuff", author: "Bob", email: "b@x.com", files: ["legacy/c.py"] }),
134
+ mk({ hash: "b2", date: "2024-01-02T23:00:00Z", subject: "more random work", author: "Bob", email: "b@x.com", files: ["legacy/d.py"] }),
135
+ ];
136
+ const a = extractDna(aliceCommits, "a@x.com");
137
+ const b = extractDna(bobCommits, "b@x.com");
138
+ const cmp = compareDna(a, b);
139
+ expect(cmp.similarity).toBeLessThan(0.7);
140
+ });
141
+ });
142
+ //# sourceMappingURL=dna.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dna.test.js","sourceRoot":"","sources":["../../src/insights/dna.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGlD,SAAS,EAAE,CAAC,CAAiI;IAC3I,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,IAAI,OAAO;QAC/B,WAAW,EAAE,CAAC,CAAC,KAAK,IAAI,mBAAmB;QAC3C,UAAU,EAAE,CAAC,CAAC,IAAI;QAClB,aAAa,EAAE,CAAC,CAAC,IAAI;QACrB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;QAClB,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,UAAU,CAAC;QAC9B,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,CAAC,CAAC,EAAE;KACf,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YACjE,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;SACpE,CAAC;QACF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;YAC9G,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;SACzG,CAAC;QACF,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC;YACpF,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;YAClF,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;SAC5E,CAAC;QACF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;YACxE,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;YACrE,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;SACzE,CAAC;QACF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;YACpF,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;SAC/D,CAAC;QACF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;YAClE,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;YAClE,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;SACnE,CAAC;QACF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YAC9D,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YAC9D,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;SAC/D,CAAC;QACF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,+CAA+C;QAC/C,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;YACzE,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;SAC1E,CAAC;QACF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC;YACzG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC;SAC7F,CAAC;QACF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;SAClE,CAAC;QACF,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACnD,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;YAC9E,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;SAC9E,CAAC;QACF,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,YAAY,GAAG;YACnB,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;YACrI,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;SACtI,CAAC;QACF,MAAM,UAAU,GAAG;YACjB,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;YACpI,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;SACvI,CAAC;QACF,MAAM,CAAC,GAAG,UAAU,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,UAAU,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * `mneme drift` — visualize topical drift in a repo's commits over time.
3
+ *
4
+ * Buckets commits into time windows (default: quarter), classifies each
5
+ * commit by intent (feature / refactor / firefight / polish / docs), then
6
+ * emits per-bucket distributions you can plot or render as a sparkline.
7
+ *
8
+ * Why novel: shipped products do not exist for this. Academic papers
9
+ * (arxiv 2110.00697, etc.) cluster commits semantically but stop at the
10
+ * paper. Mneme's drift command brings it to the CLI.
11
+ */
12
+ import type { Commit } from "../types.js";
13
+ export type DriftKind = "feature" | "refactor" | "firefight" | "polish" | "docs" | "other";
14
+ export interface DriftBucket {
15
+ /** Window label e.g. "2024-Q1" or "2024-08". */
16
+ label: string;
17
+ fromDate: string;
18
+ toDate: string;
19
+ /** Total commits in window. */
20
+ total: number;
21
+ /** Counts by drift kind. */
22
+ byKind: Record<DriftKind, number>;
23
+ /** Dominant kind for this window (highest count). */
24
+ dominant: DriftKind;
25
+ }
26
+ export interface DriftReport {
27
+ /** Granularity used. */
28
+ granularity: "quarter" | "month";
29
+ buckets: DriftBucket[];
30
+ /** Insights derived from the trajectory. */
31
+ insights: DriftInsight[];
32
+ }
33
+ export interface DriftInsight {
34
+ kind: "burnout" | "recovery" | "rewrite-cluster" | "polish-streak" | "shift";
35
+ fromBucket: string;
36
+ toBucket: string;
37
+ description: string;
38
+ }
39
+ export declare function classifyCommit(c: Commit): DriftKind;
40
+ export declare function buildDrift(commits: Commit[], opts?: {
41
+ granularity?: "quarter" | "month";
42
+ }): DriftReport;
43
+ //# sourceMappingURL=drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift.d.ts","sourceRoot":"","sources":["../../src/insights/drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3F,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClC,qDAAqD;IACrD,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,wBAAwB;IACxB,WAAW,EAAE,SAAS,GAAG,OAAO,CAAC;IACjC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,4CAA4C;IAC5C,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,iBAAiB,GAAG,eAAe,GAAG,OAAO,CAAC;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAUD,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAQnD;AAED,wBAAgB,UAAU,CACxB,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;CAAO,GAC/C,WAAW,CAoDb"}