@mneme-ai/core 0.12.0 → 0.14.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/insights/cluster.d.ts +52 -0
- package/dist/insights/cluster.d.ts.map +1 -0
- package/dist/insights/cluster.js +154 -0
- package/dist/insights/cluster.js.map +1 -0
- package/dist/insights/cluster.test.d.ts +2 -0
- package/dist/insights/cluster.test.d.ts.map +1 -0
- package/dist/insights/cluster.test.js +106 -0
- package/dist/insights/cluster.test.js.map +1 -0
- package/dist/insights/export-bundle.d.ts +53 -0
- package/dist/insights/export-bundle.d.ts.map +1 -0
- package/dist/insights/export-bundle.js +156 -0
- package/dist/insights/export-bundle.js.map +1 -0
- package/dist/insights/export-bundle.test.d.ts +2 -0
- package/dist/insights/export-bundle.test.d.ts.map +1 -0
- package/dist/insights/export-bundle.test.js +92 -0
- package/dist/insights/export-bundle.test.js.map +1 -0
- package/dist/insights/index.d.ts +4 -0
- package/dist/insights/index.d.ts.map +1 -1
- package/dist/insights/index.js +4 -0
- package/dist/insights/index.js.map +1 -1
- package/dist/insights/manage.d.ts +60 -0
- package/dist/insights/manage.d.ts.map +1 -0
- package/dist/insights/manage.js +110 -0
- package/dist/insights/manage.js.map +1 -0
- package/dist/insights/manage.test.d.ts +2 -0
- package/dist/insights/manage.test.d.ts.map +1 -0
- package/dist/insights/manage.test.js +94 -0
- package/dist/insights/manage.test.js.map +1 -0
- package/dist/insights/network.d.ts +59 -0
- package/dist/insights/network.d.ts.map +1 -0
- package/dist/insights/network.js +231 -0
- package/dist/insights/network.js.map +1 -0
- package/dist/insights/network.test.d.ts +2 -0
- package/dist/insights/network.test.d.ts.map +1 -0
- package/dist/insights/network.test.js +100 -0
- package/dist/insights/network.test.js.map +1 -0
- package/dist/retrieve/hallucination-guard.test.d.ts +2 -0
- package/dist/retrieve/hallucination-guard.test.d.ts.map +1 -0
- package/dist/retrieve/hallucination-guard.test.js +130 -0
- package/dist/retrieve/hallucination-guard.test.js.map +1 -0
- package/dist/retrieve/synthesize.d.ts +38 -2
- package/dist/retrieve/synthesize.d.ts.map +1 -1
- package/dist/retrieve/synthesize.js +135 -5
- package/dist/retrieve/synthesize.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mneme cluster` — semantic clustering of commit messages.
|
|
3
|
+
*
|
|
4
|
+
* Closes the "commit message NLP clustering" gap from the landscape
|
|
5
|
+
* survey: academic papers (arxiv 2110.00697) cluster commits semantically
|
|
6
|
+
* but never ship. Mneme ships it.
|
|
7
|
+
*
|
|
8
|
+
* Design choices:
|
|
9
|
+
* - We DON'T ship a heavyweight embedding pipeline here. Instead we
|
|
10
|
+
* use lightweight token shingles + Jaccard similarity, which gives
|
|
11
|
+
* ~80% of the value at near-zero cost and zero deps. When commits
|
|
12
|
+
* have embeddings indexed (via @mneme-ai/embeddings), the caller
|
|
13
|
+
* can pass them in and we'll use cosine instead.
|
|
14
|
+
* - Clustering is single-pass agglomerative — for a few thousand
|
|
15
|
+
* commits it's fast enough; for 100k commits the caller should
|
|
16
|
+
* pre-filter by date / path.
|
|
17
|
+
* - Cluster topics are extracted by surfacing the top-N tokens that
|
|
18
|
+
* appear in ≥ K of a cluster's commit subjects (cluster-defining
|
|
19
|
+
* vocabulary).
|
|
20
|
+
*
|
|
21
|
+
* Pure data extraction. CLI renders.
|
|
22
|
+
*/
|
|
23
|
+
import type { Commit } from "../types.js";
|
|
24
|
+
export interface CommitCluster {
|
|
25
|
+
id: number;
|
|
26
|
+
/** Number of commits in this cluster. */
|
|
27
|
+
size: number;
|
|
28
|
+
/** Top vocabulary terms shared across the cluster's commit subjects. */
|
|
29
|
+
topTerms: string[];
|
|
30
|
+
/** Sample commits (most representative — closest to the cluster centroid). */
|
|
31
|
+
samples: Commit[];
|
|
32
|
+
/** Date range covered by this cluster. */
|
|
33
|
+
fromDate: string;
|
|
34
|
+
toDate: string;
|
|
35
|
+
/** Cluster cohesion 0..1 — average pairwise similarity. */
|
|
36
|
+
cohesion: number;
|
|
37
|
+
}
|
|
38
|
+
export interface ClusterReport {
|
|
39
|
+
/** Total commits considered. */
|
|
40
|
+
totalCommits: number;
|
|
41
|
+
/** Resulting clusters, sorted by size descending. */
|
|
42
|
+
clusters: CommitCluster[];
|
|
43
|
+
/** Commits that didn't fit any cluster (singletons). */
|
|
44
|
+
outliers: Commit[];
|
|
45
|
+
}
|
|
46
|
+
export declare function buildClusters(commits: Commit[], opts?: {
|
|
47
|
+
similarityFloor?: number;
|
|
48
|
+
minClusterSize?: number;
|
|
49
|
+
maxSamplesPerCluster?: number;
|
|
50
|
+
embeddings?: Map<string, Float32Array>;
|
|
51
|
+
}): ClusterReport;
|
|
52
|
+
//# sourceMappingURL=cluster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/insights/cluster.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAUD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IACJ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACnC,GACL,aAAa,CAmEf"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
const STOPWORDS = new Set([
|
|
2
|
+
"the", "a", "an", "of", "to", "in", "on", "for", "and", "or", "with", "add", "added", "fix",
|
|
3
|
+
"remove", "update", "change", "make", "made", "new", "old", "this", "that", "is", "are", "be",
|
|
4
|
+
"was", "were", "my", "our", "your", "i", "we", "you", "it", "its", "into", "from", "by", "at",
|
|
5
|
+
"feat", "chore", "docs", "test", "refactor", "style", "build", "ci", "perf", "revert",
|
|
6
|
+
"merge", "branch", "pr", "issue", "close", "closes", "fixes",
|
|
7
|
+
]);
|
|
8
|
+
export function buildClusters(commits, opts = {}) {
|
|
9
|
+
const floor = opts.similarityFloor ?? 0.3;
|
|
10
|
+
const minSize = opts.minClusterSize ?? 2;
|
|
11
|
+
const maxSamples = opts.maxSamplesPerCluster ?? 3;
|
|
12
|
+
if (commits.length === 0) {
|
|
13
|
+
return { totalCommits: 0, clusters: [], outliers: [] };
|
|
14
|
+
}
|
|
15
|
+
const useEmbeddings = (opts.embeddings?.size ?? 0) > 0;
|
|
16
|
+
// Pre-tokenize each commit for cheap reuse
|
|
17
|
+
const tokenized = commits.map((c) => ({
|
|
18
|
+
commit: c,
|
|
19
|
+
tokens: tokenizeSet(`${c.subject}\n${c.body || ""}`),
|
|
20
|
+
vec: opts.embeddings?.get(c.hash),
|
|
21
|
+
}));
|
|
22
|
+
// Greedy single-pass: each commit joins the first cluster that exceeds floor
|
|
23
|
+
const clusters = [];
|
|
24
|
+
for (const item of tokenized) {
|
|
25
|
+
let joined = false;
|
|
26
|
+
for (const cluster of clusters) {
|
|
27
|
+
const sample = cluster[0];
|
|
28
|
+
const sim = useEmbeddings && sample.vec && item.vec
|
|
29
|
+
? cosine(sample.vec, item.vec)
|
|
30
|
+
: jaccard(sample.tokens, item.tokens);
|
|
31
|
+
if (sim >= floor) {
|
|
32
|
+
cluster.push(item);
|
|
33
|
+
joined = true;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (!joined)
|
|
38
|
+
clusters.push([item]);
|
|
39
|
+
}
|
|
40
|
+
// Build report
|
|
41
|
+
const result = [];
|
|
42
|
+
const outliers = [];
|
|
43
|
+
let id = 1;
|
|
44
|
+
for (const cluster of clusters) {
|
|
45
|
+
if (cluster.length < minSize) {
|
|
46
|
+
for (const it of cluster)
|
|
47
|
+
outliers.push(it.commit);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const allCommits = cluster.map((c) => c.commit).sort((a, b) => a.authorDate.localeCompare(b.authorDate));
|
|
51
|
+
result.push({
|
|
52
|
+
id: id++,
|
|
53
|
+
size: cluster.length,
|
|
54
|
+
topTerms: clusterTopTerms(cluster.map((c) => c.tokens)),
|
|
55
|
+
samples: pickSamples(cluster, maxSamples),
|
|
56
|
+
fromDate: allCommits[0].authorDate.slice(0, 10),
|
|
57
|
+
toDate: allCommits[allCommits.length - 1].authorDate.slice(0, 10),
|
|
58
|
+
cohesion: avgCohesion(cluster, useEmbeddings),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
result.sort((a, b) => b.size - a.size);
|
|
62
|
+
return {
|
|
63
|
+
totalCommits: commits.length,
|
|
64
|
+
clusters: result,
|
|
65
|
+
outliers,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function tokenizeSet(text) {
|
|
69
|
+
const out = new Set();
|
|
70
|
+
for (const t of text
|
|
71
|
+
.toLowerCase()
|
|
72
|
+
.replace(/[^a-z0-9_/.-]+/g, " ")
|
|
73
|
+
.split(/\s+/)) {
|
|
74
|
+
if (!t || t.length < 3)
|
|
75
|
+
continue;
|
|
76
|
+
if (STOPWORDS.has(t))
|
|
77
|
+
continue;
|
|
78
|
+
out.add(t);
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
function jaccard(a, b) {
|
|
83
|
+
if (a.size === 0 && b.size === 0)
|
|
84
|
+
return 1;
|
|
85
|
+
let inter = 0;
|
|
86
|
+
for (const x of a)
|
|
87
|
+
if (b.has(x))
|
|
88
|
+
inter++;
|
|
89
|
+
const union = a.size + b.size - inter;
|
|
90
|
+
return union === 0 ? 0 : inter / union;
|
|
91
|
+
}
|
|
92
|
+
function cosine(a, b) {
|
|
93
|
+
let dot = 0, na = 0, nb = 0;
|
|
94
|
+
const n = Math.min(a.length, b.length);
|
|
95
|
+
for (let i = 0; i < n; i++) {
|
|
96
|
+
const ai = a[i] ?? 0;
|
|
97
|
+
const bi = b[i] ?? 0;
|
|
98
|
+
dot += ai * bi;
|
|
99
|
+
na += ai * ai;
|
|
100
|
+
nb += bi * bi;
|
|
101
|
+
}
|
|
102
|
+
const denom = Math.sqrt(na) * Math.sqrt(nb);
|
|
103
|
+
return denom === 0 ? 0 : dot / denom;
|
|
104
|
+
}
|
|
105
|
+
function clusterTopTerms(tokenSets) {
|
|
106
|
+
if (tokenSets.length === 0)
|
|
107
|
+
return [];
|
|
108
|
+
const docFreq = new Map();
|
|
109
|
+
for (const ts of tokenSets) {
|
|
110
|
+
for (const t of ts)
|
|
111
|
+
docFreq.set(t, (docFreq.get(t) ?? 0) + 1);
|
|
112
|
+
}
|
|
113
|
+
const minDocsForTerm = Math.max(2, Math.ceil(tokenSets.length / 3));
|
|
114
|
+
return [...docFreq.entries()]
|
|
115
|
+
.filter(([, count]) => count >= minDocsForTerm)
|
|
116
|
+
.sort((a, b) => b[1] - a[1])
|
|
117
|
+
.slice(0, 5)
|
|
118
|
+
.map(([term]) => term);
|
|
119
|
+
}
|
|
120
|
+
function pickSamples(items, k) {
|
|
121
|
+
if (items.length <= k)
|
|
122
|
+
return items.map((i) => i.commit);
|
|
123
|
+
// Closest to centroid (by avg jaccard to others)
|
|
124
|
+
const scored = items.map((it) => {
|
|
125
|
+
let total = 0;
|
|
126
|
+
for (const other of items) {
|
|
127
|
+
if (other === it)
|
|
128
|
+
continue;
|
|
129
|
+
total += jaccard(it.tokens, other.tokens);
|
|
130
|
+
}
|
|
131
|
+
return { it, score: total };
|
|
132
|
+
});
|
|
133
|
+
scored.sort((a, b) => b.score - a.score);
|
|
134
|
+
return scored.slice(0, k).map((s) => s.it.commit);
|
|
135
|
+
}
|
|
136
|
+
function avgCohesion(items, useEmbeddings) {
|
|
137
|
+
if (items.length < 2)
|
|
138
|
+
return 1;
|
|
139
|
+
let sum = 0;
|
|
140
|
+
let pairs = 0;
|
|
141
|
+
for (let i = 0; i < items.length; i++) {
|
|
142
|
+
for (let j = i + 1; j < items.length; j++) {
|
|
143
|
+
const a = items[i];
|
|
144
|
+
const b = items[j];
|
|
145
|
+
const sim = useEmbeddings && a.vec && b.vec
|
|
146
|
+
? cosine(a.vec, b.vec)
|
|
147
|
+
: jaccard(a.tokens, b.tokens);
|
|
148
|
+
sum += sim;
|
|
149
|
+
pairs++;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return pairs === 0 ? 0 : Number((sum / pairs).toFixed(3));
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=cluster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.js","sourceRoot":"","sources":["../../src/insights/cluster.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.test.d.ts","sourceRoot":"","sources":["../../src/insights/cluster.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { buildClusters } from "./cluster.js";
|
|
3
|
+
function mk(p) {
|
|
4
|
+
return {
|
|
5
|
+
hash: p.hash,
|
|
6
|
+
shortHash: p.hash.slice(0, 7),
|
|
7
|
+
authorName: "Test",
|
|
8
|
+
authorEmail: "t@e.com",
|
|
9
|
+
authorDate: p.date ?? "2024-01-01",
|
|
10
|
+
committerDate: p.date ?? "2024-01-01",
|
|
11
|
+
subject: p.subject,
|
|
12
|
+
body: p.body ?? "",
|
|
13
|
+
files: [],
|
|
14
|
+
parents: [],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
describe("buildClusters", () => {
|
|
18
|
+
it("returns empty when no commits", () => {
|
|
19
|
+
const r = buildClusters([]);
|
|
20
|
+
expect(r.totalCommits).toBe(0);
|
|
21
|
+
expect(r.clusters).toHaveLength(0);
|
|
22
|
+
});
|
|
23
|
+
it("groups similar commits into one cluster", () => {
|
|
24
|
+
const commits = [
|
|
25
|
+
mk({ hash: "a1", subject: "add caching layer to api responses" }),
|
|
26
|
+
mk({ hash: "a2", subject: "extend caching to user objects" }),
|
|
27
|
+
mk({ hash: "a3", subject: "improve caching hit ratio" }),
|
|
28
|
+
mk({ hash: "b1", subject: "fix typo in README" }),
|
|
29
|
+
mk({ hash: "b2", subject: "fix typo in CHANGELOG" }),
|
|
30
|
+
];
|
|
31
|
+
const r = buildClusters(commits, { similarityFloor: 0.1, minClusterSize: 2 });
|
|
32
|
+
const cacheCluster = r.clusters.find((c) => c.topTerms.includes("caching"));
|
|
33
|
+
expect(cacheCluster).toBeDefined();
|
|
34
|
+
expect(cacheCluster.size).toBeGreaterThanOrEqual(2);
|
|
35
|
+
});
|
|
36
|
+
it("singletons go to outliers when minClusterSize >= 2", () => {
|
|
37
|
+
const commits = [
|
|
38
|
+
mk({ hash: "a1", subject: "completely unique subject xyz" }),
|
|
39
|
+
mk({ hash: "a2", subject: "another distinct subject abc" }),
|
|
40
|
+
];
|
|
41
|
+
const r = buildClusters(commits, { similarityFloor: 0.5, minClusterSize: 2 });
|
|
42
|
+
expect(r.outliers.length).toBe(2);
|
|
43
|
+
});
|
|
44
|
+
it("clusters are sorted by size descending", () => {
|
|
45
|
+
const commits = [
|
|
46
|
+
mk({ hash: "a1", subject: "add caching layer" }),
|
|
47
|
+
mk({ hash: "a2", subject: "add caching to api" }),
|
|
48
|
+
mk({ hash: "a3", subject: "add caching index" }),
|
|
49
|
+
mk({ hash: "b1", subject: "fix bug in handler" }),
|
|
50
|
+
mk({ hash: "b2", subject: "fix bug in router" }),
|
|
51
|
+
];
|
|
52
|
+
const r = buildClusters(commits, { similarityFloor: 0.2, minClusterSize: 2 });
|
|
53
|
+
for (let i = 1; i < r.clusters.length; i++) {
|
|
54
|
+
expect(r.clusters[i - 1].size).toBeGreaterThanOrEqual(r.clusters[i].size);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
it("topTerms reflect shared cluster vocabulary", () => {
|
|
58
|
+
const commits = [
|
|
59
|
+
mk({ hash: "a1", subject: "rewrite authentication middleware" }),
|
|
60
|
+
mk({ hash: "a2", subject: "rewrite authentication tests" }),
|
|
61
|
+
mk({ hash: "a3", subject: "polish authentication" }),
|
|
62
|
+
];
|
|
63
|
+
const r = buildClusters(commits, { similarityFloor: 0.1, minClusterSize: 2 });
|
|
64
|
+
const auth = r.clusters[0];
|
|
65
|
+
expect(auth).toBeDefined();
|
|
66
|
+
expect(auth.topTerms).toContain("authentication");
|
|
67
|
+
});
|
|
68
|
+
it("samples never exceed maxSamplesPerCluster", () => {
|
|
69
|
+
const commits = Array.from({ length: 8 }, (_, i) => mk({ hash: `a${i}`, subject: `caching ${i} layer api` }));
|
|
70
|
+
const r = buildClusters(commits, { similarityFloor: 0.15, minClusterSize: 2, maxSamplesPerCluster: 3 });
|
|
71
|
+
for (const c of r.clusters) {
|
|
72
|
+
expect(c.samples.length).toBeLessThanOrEqual(3);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
it("cohesion of single-commit cluster is 1", () => {
|
|
76
|
+
const commits = [mk({ hash: "a1", subject: "lonely commit subject" })];
|
|
77
|
+
const r = buildClusters(commits, { similarityFloor: 0, minClusterSize: 1 });
|
|
78
|
+
if (r.clusters.length > 0) {
|
|
79
|
+
expect(r.clusters[0].cohesion).toBe(1);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
it("date range covers earliest and latest commit in cluster", () => {
|
|
83
|
+
const commits = [
|
|
84
|
+
mk({ hash: "a1", subject: "add caching layer", date: "2024-01-01" }),
|
|
85
|
+
mk({ hash: "a2", subject: "add caching tests", date: "2024-06-15" }),
|
|
86
|
+
];
|
|
87
|
+
const r = buildClusters(commits, { similarityFloor: 0.1, minClusterSize: 2 });
|
|
88
|
+
const c = r.clusters[0];
|
|
89
|
+
if (c) {
|
|
90
|
+
expect(c.fromDate).toBe("2024-01-01");
|
|
91
|
+
expect(c.toDate).toBe("2024-06-15");
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
it("respects similarityFloor — high floor produces more clusters", () => {
|
|
95
|
+
const commits = [
|
|
96
|
+
mk({ hash: "a1", subject: "add caching" }),
|
|
97
|
+
mk({ hash: "a2", subject: "add cache" }),
|
|
98
|
+
mk({ hash: "a3", subject: "add caching layer" }),
|
|
99
|
+
];
|
|
100
|
+
const lowFloor = buildClusters(commits, { similarityFloor: 0.05, minClusterSize: 2 });
|
|
101
|
+
const highFloor = buildClusters(commits, { similarityFloor: 0.95, minClusterSize: 2 });
|
|
102
|
+
// High floor splits more aggressively → fewer joins → more outliers
|
|
103
|
+
expect(highFloor.outliers.length).toBeGreaterThanOrEqual(lowFloor.outliers.length);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=cluster.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster.test.js","sourceRoot":"","sources":["../../src/insights/cluster.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mneme export` — universal export bundle.
|
|
3
|
+
*
|
|
4
|
+
* Closes the "exportable" gap: existing tools either don't export at all
|
|
5
|
+
* or export a single fragment. Mneme bundles every analysis into one
|
|
6
|
+
* shareable artifact (JSON + Markdown + optional HTML) that another team
|
|
7
|
+
* can consume without running Mneme themselves.
|
|
8
|
+
*
|
|
9
|
+
* Pure data extraction. Uses other insight builders as inputs.
|
|
10
|
+
*/
|
|
11
|
+
import type { Commit, FileChange } from "../types.js";
|
|
12
|
+
import { extractDna } from "./dna.js";
|
|
13
|
+
import { buildDrift } from "./drift.js";
|
|
14
|
+
import { buildChronicle } from "./chronicle.js";
|
|
15
|
+
import { buildOracle } from "./oracle.js";
|
|
16
|
+
import { buildConstellation } from "./constellation.js";
|
|
17
|
+
import { buildClusters } from "./cluster.js";
|
|
18
|
+
import { buildNetwork } from "./network.js";
|
|
19
|
+
import { buildManage } from "./manage.js";
|
|
20
|
+
import { buildGhostReport } from "./ghost.js";
|
|
21
|
+
export interface ExportBundle {
|
|
22
|
+
/** ISO timestamp of when the bundle was generated. */
|
|
23
|
+
generatedAt: string;
|
|
24
|
+
/** Mneme version. */
|
|
25
|
+
version: string;
|
|
26
|
+
/** Repo metadata. */
|
|
27
|
+
repo: {
|
|
28
|
+
totalCommits: number;
|
|
29
|
+
totalAuthors: number;
|
|
30
|
+
fromDate: string;
|
|
31
|
+
toDate: string;
|
|
32
|
+
};
|
|
33
|
+
/** Top-author DNA strands. */
|
|
34
|
+
topAuthorsDna: ReturnType<typeof extractDna>[];
|
|
35
|
+
drift: ReturnType<typeof buildDrift>;
|
|
36
|
+
chronicle: ReturnType<typeof buildChronicle>;
|
|
37
|
+
oracle: ReturnType<typeof buildOracle>;
|
|
38
|
+
constellation: ReturnType<typeof buildConstellation>;
|
|
39
|
+
clusters: ReturnType<typeof buildClusters>;
|
|
40
|
+
network: ReturnType<typeof buildNetwork>;
|
|
41
|
+
manage: ReturnType<typeof buildManage>;
|
|
42
|
+
ghost: ReturnType<typeof buildGhostReport>;
|
|
43
|
+
}
|
|
44
|
+
export interface ExportOptions {
|
|
45
|
+
version?: string;
|
|
46
|
+
topAuthors?: number;
|
|
47
|
+
nowMs?: number;
|
|
48
|
+
fileChanges?: FileChange[];
|
|
49
|
+
}
|
|
50
|
+
export declare function buildExportBundle(commits: Commit[], opts?: ExportOptions): ExportBundle;
|
|
51
|
+
/** Render the bundle as a single Markdown report. */
|
|
52
|
+
export declare function renderExportMarkdown(bundle: ExportBundle): string;
|
|
53
|
+
//# sourceMappingURL=export-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-bundle.d.ts","sourceRoot":"","sources":["../../src/insights/export-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAmB,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,IAAI,EAAE;QACJ,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,8BAA8B;IAC9B,aAAa,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,EAAE,CAAC;IAC/C,KAAK,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IACrC,SAAS,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;IAC7C,MAAM,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACvC,aAAa,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;IACrD,QAAQ,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;IAC3C,OAAO,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACzC,MAAM,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACvC,KAAK,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE,aAAkB,GACvB,YAAY,CAsCd;AAED,qDAAqD;AACrD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAsHjE"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { extractDna } from "./dna.js";
|
|
2
|
+
import { buildDrift } from "./drift.js";
|
|
3
|
+
import { buildChronicle, renderChronicle } from "./chronicle.js";
|
|
4
|
+
import { buildOracle } from "./oracle.js";
|
|
5
|
+
import { buildConstellation } from "./constellation.js";
|
|
6
|
+
import { buildClusters } from "./cluster.js";
|
|
7
|
+
import { buildNetwork } from "./network.js";
|
|
8
|
+
import { buildManage } from "./manage.js";
|
|
9
|
+
import { buildGhostReport } from "./ghost.js";
|
|
10
|
+
export function buildExportBundle(commits, opts = {}) {
|
|
11
|
+
const sorted = [...commits].sort((a, b) => a.authorDate.localeCompare(b.authorDate));
|
|
12
|
+
const fromDate = sorted.length > 0 ? sorted[0].authorDate.slice(0, 10) : "";
|
|
13
|
+
const toDate = sorted.length > 0 ? sorted[sorted.length - 1].authorDate.slice(0, 10) : "";
|
|
14
|
+
const authors = new Map();
|
|
15
|
+
for (const c of commits) {
|
|
16
|
+
const a = c.authorEmail || c.authorName;
|
|
17
|
+
authors.set(a, (authors.get(a) ?? 0) + 1);
|
|
18
|
+
}
|
|
19
|
+
const topAuthors = [...authors.entries()]
|
|
20
|
+
.sort((a, b) => b[1] - a[1])
|
|
21
|
+
.slice(0, opts.topAuthors ?? 5)
|
|
22
|
+
.map(([author]) => author);
|
|
23
|
+
const topAuthorsDna = topAuthors.map((a) => extractDna(commits, a));
|
|
24
|
+
return {
|
|
25
|
+
generatedAt: new Date(opts.nowMs ?? Date.now()).toISOString(),
|
|
26
|
+
version: opts.version ?? "0.13.0",
|
|
27
|
+
repo: {
|
|
28
|
+
totalCommits: commits.length,
|
|
29
|
+
totalAuthors: authors.size,
|
|
30
|
+
fromDate,
|
|
31
|
+
toDate,
|
|
32
|
+
},
|
|
33
|
+
topAuthorsDna,
|
|
34
|
+
drift: buildDrift(commits),
|
|
35
|
+
chronicle: buildChronicle(commits),
|
|
36
|
+
oracle: buildOracle(commits, { nowMs: opts.nowMs }),
|
|
37
|
+
constellation: buildConstellation(commits),
|
|
38
|
+
clusters: buildClusters(commits, { similarityFloor: 0.15, minClusterSize: 3 }),
|
|
39
|
+
network: buildNetwork(commits),
|
|
40
|
+
manage: buildManage(commits, { nowMs: opts.nowMs }),
|
|
41
|
+
ghost: buildGhostReport(commits, opts.fileChanges ?? [], { nowMs: opts.nowMs }),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Render the bundle as a single Markdown report. */
|
|
45
|
+
export function renderExportMarkdown(bundle) {
|
|
46
|
+
const lines = [];
|
|
47
|
+
lines.push("# Mneme — Codebase Bundle");
|
|
48
|
+
lines.push("");
|
|
49
|
+
lines.push(`> Generated ${bundle.generatedAt} · Mneme ${bundle.version}`);
|
|
50
|
+
lines.push("");
|
|
51
|
+
lines.push(`**Repo summary** — ${bundle.repo.totalCommits} commits across ${bundle.repo.totalAuthors} authors, ${bundle.repo.fromDate} → ${bundle.repo.toDate}.`);
|
|
52
|
+
lines.push("");
|
|
53
|
+
// Health
|
|
54
|
+
lines.push("## 📊 Team Health");
|
|
55
|
+
lines.push("");
|
|
56
|
+
lines.push(`- Overall score: **${pct(bundle.manage.health.overall)}**`);
|
|
57
|
+
lines.push(`- Trajectory: **${bundle.manage.health.trajectory.dominant}** (${bundle.manage.health.trajectory.label})`);
|
|
58
|
+
lines.push(`- Predicted collisions: **${bundle.manage.health.predictedCollisions}**`);
|
|
59
|
+
lines.push(`- Max succession risk: **${pct(bundle.manage.health.maxSuccessionRisk)}**`);
|
|
60
|
+
lines.push("");
|
|
61
|
+
for (const note of bundle.manage.health.notes) {
|
|
62
|
+
lines.push(`- _${note}_`);
|
|
63
|
+
}
|
|
64
|
+
lines.push("");
|
|
65
|
+
// Drift
|
|
66
|
+
lines.push("## 📈 Drift trajectory");
|
|
67
|
+
lines.push("");
|
|
68
|
+
for (const b of bundle.drift.buckets) {
|
|
69
|
+
lines.push(`- **${b.label}** — ${b.total} commits — dominant: \`${b.dominant}\``);
|
|
70
|
+
}
|
|
71
|
+
if (bundle.drift.insights.length > 0) {
|
|
72
|
+
lines.push("");
|
|
73
|
+
lines.push("**Insights:**");
|
|
74
|
+
for (const i of bundle.drift.insights) {
|
|
75
|
+
lines.push(`- _${i.fromBucket} → ${i.toBucket}_: ${i.description}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
lines.push("");
|
|
79
|
+
// Chronicle (truncated to chapter list)
|
|
80
|
+
lines.push("## 📖 Chronicle (chapters)");
|
|
81
|
+
lines.push("");
|
|
82
|
+
for (const ch of bundle.chronicle.chapters) {
|
|
83
|
+
lines.push(`- **Chapter ${ch.number} · ${ch.title}** (${ch.fromDate} → ${ch.toDate}, ${ch.commits.length} commits, protagonist @${ch.protagonist})`);
|
|
84
|
+
}
|
|
85
|
+
lines.push("");
|
|
86
|
+
// DNA
|
|
87
|
+
lines.push("## 🧬 Top contributors (DNA hashes)");
|
|
88
|
+
lines.push("");
|
|
89
|
+
for (const d of bundle.topAuthorsDna) {
|
|
90
|
+
lines.push(`- **${d.author}** — ${d.commitCount} commits — DNA \`${d.hash}\` — peak ${d.hours.peakWindow}, conventional commits ${pct(d.style.conventionalRatio)}`);
|
|
91
|
+
}
|
|
92
|
+
lines.push("");
|
|
93
|
+
// Network
|
|
94
|
+
lines.push("## 🕸 Author network");
|
|
95
|
+
lines.push("");
|
|
96
|
+
lines.push(`Top edges (collaboration weight):`);
|
|
97
|
+
for (const e of bundle.network.edges.slice(0, 10)) {
|
|
98
|
+
const terms = e.sharedTerms.slice(0, 3).join(", ");
|
|
99
|
+
lines.push(`- ${e.authorA} ⟷ ${e.authorB}: weight ${pct(e.weight)} — shared: ${terms || "(none)"}`);
|
|
100
|
+
}
|
|
101
|
+
if (bundle.network.bridges.length > 0) {
|
|
102
|
+
lines.push("");
|
|
103
|
+
lines.push(`**Bridges**: ${bundle.network.bridges.join(", ")}`);
|
|
104
|
+
}
|
|
105
|
+
lines.push("");
|
|
106
|
+
// Clusters
|
|
107
|
+
lines.push("## 🧠 Semantic commit clusters");
|
|
108
|
+
lines.push("");
|
|
109
|
+
for (const c of bundle.clusters.clusters.slice(0, 8)) {
|
|
110
|
+
lines.push(`- **Cluster ${c.id}** (${c.size} commits, cohesion ${pct(c.cohesion)}) — terms: ${c.topTerms.join(", ")}`);
|
|
111
|
+
}
|
|
112
|
+
lines.push("");
|
|
113
|
+
// Oracle
|
|
114
|
+
lines.push("## 🔮 Oracle predictions");
|
|
115
|
+
lines.push("");
|
|
116
|
+
if (bundle.oracle.collisions.length === 0) {
|
|
117
|
+
lines.push("_No high-probability collisions predicted._");
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
for (const c of bundle.oracle.collisions.slice(0, 5)) {
|
|
121
|
+
lines.push(`- **${c.filePath}** — ${c.authorA} ⨯ ${c.authorB}, joint P = ${pct(c.jointProbability)}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
lines.push("");
|
|
125
|
+
// Constellation summary
|
|
126
|
+
lines.push("## 🌌 Constellation");
|
|
127
|
+
lines.push("");
|
|
128
|
+
lines.push(`- ${bundle.constellation.fileStars.length} file-stars`);
|
|
129
|
+
lines.push(`- ${bundle.constellation.authorOrbitals.length} orbitals`);
|
|
130
|
+
lines.push(`- ${bundle.constellation.fileEdges.length} co-edit edges`);
|
|
131
|
+
lines.push(`- ${bundle.constellation.clusterCount} clusters`);
|
|
132
|
+
lines.push("");
|
|
133
|
+
// Ghost
|
|
134
|
+
lines.push("## 👻 Ghost code");
|
|
135
|
+
lines.push("");
|
|
136
|
+
if (bundle.ghost.ghostFiles.length === 0) {
|
|
137
|
+
lines.push("_No significant ghosts._");
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
for (const g of bundle.ghost.ghostFiles.slice(0, 8)) {
|
|
141
|
+
lines.push(`- **${g.path}** — ghostliness ${pct(g.ghostliness)} — _${g.reason}_`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
lines.push("");
|
|
145
|
+
// Embedded full chronicle
|
|
146
|
+
lines.push("---");
|
|
147
|
+
lines.push("");
|
|
148
|
+
lines.push("# Appendix · Full Chronicle");
|
|
149
|
+
lines.push("");
|
|
150
|
+
lines.push(renderChronicle(bundle.chronicle));
|
|
151
|
+
return lines.join("\n");
|
|
152
|
+
}
|
|
153
|
+
function pct(r) {
|
|
154
|
+
return `${Math.round(r * 100)}%`;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=export-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-bundle.js","sourceRoot":"","sources":["../../src/insights/export-bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-bundle.test.d.ts","sourceRoot":"","sources":["../../src/insights/export-bundle.test.ts"],"names":[],"mappings":""}
|