@mneme-ai/core 0.11.0 → 0.12.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/chronicle.d.ts +41 -0
- package/dist/insights/chronicle.d.ts.map +1 -0
- package/dist/insights/chronicle.js +169 -0
- package/dist/insights/chronicle.js.map +1 -0
- package/dist/insights/chronicle.test.d.ts +2 -0
- package/dist/insights/chronicle.test.d.ts.map +1 -0
- package/dist/insights/chronicle.test.js +92 -0
- package/dist/insights/chronicle.test.js.map +1 -0
- package/dist/insights/constellation.d.ts +63 -0
- package/dist/insights/constellation.d.ts.map +1 -0
- package/dist/insights/constellation.js +147 -0
- package/dist/insights/constellation.js.map +1 -0
- package/dist/insights/constellation.test.d.ts +2 -0
- package/dist/insights/constellation.test.d.ts.map +1 -0
- package/dist/insights/constellation.test.js +105 -0
- package/dist/insights/constellation.test.js.map +1 -0
- package/dist/insights/dna.d.ts +100 -0
- package/dist/insights/dna.d.ts.map +1 -0
- package/dist/insights/dna.js +264 -0
- package/dist/insights/dna.js.map +1 -0
- package/dist/insights/dna.test.d.ts +2 -0
- package/dist/insights/dna.test.d.ts.map +1 -0
- package/dist/insights/dna.test.js +142 -0
- package/dist/insights/dna.test.js.map +1 -0
- package/dist/insights/drift.d.ts +43 -0
- package/dist/insights/drift.d.ts.map +1 -0
- package/dist/insights/drift.js +170 -0
- package/dist/insights/drift.js.map +1 -0
- package/dist/insights/drift.test.d.ts +2 -0
- package/dist/insights/drift.test.d.ts.map +1 -0
- package/dist/insights/drift.test.js +126 -0
- package/dist/insights/drift.test.js.map +1 -0
- package/dist/insights/index.d.ts +5 -0
- package/dist/insights/index.d.ts.map +1 -1
- package/dist/insights/index.js +5 -0
- package/dist/insights/index.js.map +1 -1
- package/dist/insights/oracle.d.ts +59 -0
- package/dist/insights/oracle.d.ts.map +1 -0
- package/dist/insights/oracle.js +0 -0
- package/dist/insights/oracle.js.map +1 -0
- package/dist/insights/oracle.test.d.ts +2 -0
- package/dist/insights/oracle.test.d.ts.map +1 -0
- package/dist/insights/oracle.test.js +133 -0
- package/dist/insights/oracle.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mneme chronicle` — auto-generate a narrative documentary of the repo,
|
|
3
|
+
* told as chapters. Detects significant epochs across the WHOLE repo
|
|
4
|
+
* (not a single file like time-machine), names each chapter, and emits
|
|
5
|
+
* markdown ready to export to PDF/EPUB.
|
|
6
|
+
*
|
|
7
|
+
* Pure data extraction. CLI renders + optional LLM polish for prose.
|
|
8
|
+
*/
|
|
9
|
+
import type { Commit } from "../types.js";
|
|
10
|
+
export interface Chapter {
|
|
11
|
+
number: number;
|
|
12
|
+
title: string;
|
|
13
|
+
/** Sub-title evoking what happened (extractive). */
|
|
14
|
+
subtitle: string;
|
|
15
|
+
fromDate: string;
|
|
16
|
+
toDate: string;
|
|
17
|
+
spanDays: number;
|
|
18
|
+
commits: Commit[];
|
|
19
|
+
/** Top contributor of this chapter. */
|
|
20
|
+
protagonist: string;
|
|
21
|
+
/** Opening paragraph (extractive — first informative commit). */
|
|
22
|
+
opening: string;
|
|
23
|
+
/** Closing paragraph. */
|
|
24
|
+
closing: string;
|
|
25
|
+
}
|
|
26
|
+
export interface Chronicle {
|
|
27
|
+
totalCommits: number;
|
|
28
|
+
totalDays: number;
|
|
29
|
+
chapters: Chapter[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Build chapters from commit history. We split history into epochs
|
|
33
|
+
* detected by long gaps OR by sudden churn shifts (rewrite events).
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildChronicle(commits: Commit[], opts?: {
|
|
36
|
+
gapDays?: number;
|
|
37
|
+
minChapterCommits?: number;
|
|
38
|
+
}): Chronicle;
|
|
39
|
+
/** Render chronicle as markdown ready to write to disk. */
|
|
40
|
+
export declare function renderChronicle(chronicle: Chronicle): string;
|
|
41
|
+
//# sourceMappingURL=chronicle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chronicle.d.ts","sourceRoot":"","sources":["../../src/insights/chronicle.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAeD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1D,SAAS,CAgEX;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CA4B5D"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const TITLES = [
|
|
2
|
+
"The Founding",
|
|
3
|
+
"The First Expansion",
|
|
4
|
+
"The Auth Wars",
|
|
5
|
+
"The Great Refactor",
|
|
6
|
+
"The Quiet Year",
|
|
7
|
+
"The Reckoning",
|
|
8
|
+
"The New Era",
|
|
9
|
+
"The Revival",
|
|
10
|
+
"The Architecture Schism",
|
|
11
|
+
"The Stabilization",
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Build chapters from commit history. We split history into epochs
|
|
15
|
+
* detected by long gaps OR by sudden churn shifts (rewrite events).
|
|
16
|
+
*/
|
|
17
|
+
export function buildChronicle(commits, opts = {}) {
|
|
18
|
+
const gapDays = opts.gapDays ?? 30;
|
|
19
|
+
const minChapter = opts.minChapterCommits ?? 5;
|
|
20
|
+
const sorted = [...commits].sort((a, b) => a.authorDate.localeCompare(b.authorDate));
|
|
21
|
+
if (sorted.length === 0) {
|
|
22
|
+
return { totalCommits: 0, totalDays: 0, chapters: [] };
|
|
23
|
+
}
|
|
24
|
+
// First pass: split by long gaps
|
|
25
|
+
const groups = [];
|
|
26
|
+
let current = [sorted[0]];
|
|
27
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
28
|
+
const prev = sorted[i - 1];
|
|
29
|
+
const cur = sorted[i];
|
|
30
|
+
const gap = (new Date(cur.authorDate).getTime() - new Date(prev.authorDate).getTime()) / 86_400_000;
|
|
31
|
+
if (gap >= gapDays && current.length >= minChapter) {
|
|
32
|
+
groups.push(current);
|
|
33
|
+
current = [cur];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
current.push(cur);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
groups.push(current);
|
|
40
|
+
// Build chapters
|
|
41
|
+
const chapters = [];
|
|
42
|
+
for (let i = 0; i < groups.length; i++) {
|
|
43
|
+
const g = groups[i];
|
|
44
|
+
if (g.length === 0)
|
|
45
|
+
continue;
|
|
46
|
+
const fromDate = g[0].authorDate.slice(0, 10);
|
|
47
|
+
const toDate = g[g.length - 1].authorDate.slice(0, 10);
|
|
48
|
+
const spanDays = Math.max(0, Math.round((new Date(toDate).getTime() - new Date(fromDate).getTime()) / 86_400_000));
|
|
49
|
+
chapters.push({
|
|
50
|
+
number: i + 1,
|
|
51
|
+
title: titleFor(i, g),
|
|
52
|
+
subtitle: subtitleFor(g),
|
|
53
|
+
fromDate,
|
|
54
|
+
toDate,
|
|
55
|
+
spanDays,
|
|
56
|
+
commits: g,
|
|
57
|
+
protagonist: protagonistOf(g),
|
|
58
|
+
opening: openingOf(g),
|
|
59
|
+
closing: closingOf(g),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const totalDays = Math.round((new Date(sorted[sorted.length - 1].authorDate).getTime() -
|
|
63
|
+
new Date(sorted[0].authorDate).getTime()) /
|
|
64
|
+
86_400_000);
|
|
65
|
+
return {
|
|
66
|
+
totalCommits: sorted.length,
|
|
67
|
+
totalDays,
|
|
68
|
+
chapters,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Render chronicle as markdown ready to write to disk. */
|
|
72
|
+
export function renderChronicle(chronicle) {
|
|
73
|
+
if (chronicle.chapters.length === 0) {
|
|
74
|
+
return "# Codebase Chronicles\n\n_No commits to chronicle yet._\n";
|
|
75
|
+
}
|
|
76
|
+
const lines = [];
|
|
77
|
+
lines.push("# Chronicles of Your Codebase");
|
|
78
|
+
lines.push("");
|
|
79
|
+
lines.push(`> ${chronicle.totalCommits} commits across ${chronicle.totalDays} days, told in ${chronicle.chapters.length} chapters.`);
|
|
80
|
+
lines.push("");
|
|
81
|
+
lines.push("---");
|
|
82
|
+
lines.push("");
|
|
83
|
+
for (const ch of chronicle.chapters) {
|
|
84
|
+
lines.push(`## Chapter ${ch.number} · ${ch.title}`);
|
|
85
|
+
lines.push("");
|
|
86
|
+
lines.push(`*${ch.subtitle}*`);
|
|
87
|
+
lines.push("");
|
|
88
|
+
lines.push(`**${ch.fromDate} → ${ch.toDate}** · ${ch.spanDays} days · ${ch.commits.length} commits · protagonist: **@${ch.protagonist}**`);
|
|
89
|
+
lines.push("");
|
|
90
|
+
lines.push(ch.opening);
|
|
91
|
+
lines.push("");
|
|
92
|
+
if (ch.closing && ch.closing !== ch.opening) {
|
|
93
|
+
lines.push(ch.closing);
|
|
94
|
+
lines.push("");
|
|
95
|
+
}
|
|
96
|
+
lines.push("---");
|
|
97
|
+
lines.push("");
|
|
98
|
+
}
|
|
99
|
+
return lines.join("\n");
|
|
100
|
+
}
|
|
101
|
+
function titleFor(idx, commits) {
|
|
102
|
+
if (idx === 0)
|
|
103
|
+
return "The Founding";
|
|
104
|
+
// detect refactor cluster
|
|
105
|
+
const text = commits
|
|
106
|
+
.map((c) => c.subject + " " + (c.body || ""))
|
|
107
|
+
.join(" ")
|
|
108
|
+
.toLowerCase();
|
|
109
|
+
if (/\b(rewrite|refactor|migrate|overhaul)\b/.test(text)) {
|
|
110
|
+
return "The Great Refactor";
|
|
111
|
+
}
|
|
112
|
+
if (/\b(hotfix|incident|outage|critical|emergency)\b/.test(text)) {
|
|
113
|
+
return "The Reckoning";
|
|
114
|
+
}
|
|
115
|
+
if (commits.length < 8) {
|
|
116
|
+
return "The Quiet Stretch";
|
|
117
|
+
}
|
|
118
|
+
return TITLES[Math.min(idx, TITLES.length - 1)] ?? `Era ${idx + 1}`;
|
|
119
|
+
}
|
|
120
|
+
function subtitleFor(commits) {
|
|
121
|
+
// Prefer the longest subject from the first 5 commits as flavor
|
|
122
|
+
const top = commits
|
|
123
|
+
.slice(0, 5)
|
|
124
|
+
.reduce((best, c) => (c.subject.length > best.subject.length ? c : best), commits[0]);
|
|
125
|
+
return truncate(top.subject, 100);
|
|
126
|
+
}
|
|
127
|
+
function protagonistOf(commits) {
|
|
128
|
+
const counts = new Map();
|
|
129
|
+
for (const c of commits) {
|
|
130
|
+
const key = c.authorName || c.authorEmail;
|
|
131
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
132
|
+
}
|
|
133
|
+
let best = "unknown";
|
|
134
|
+
let bestN = -1;
|
|
135
|
+
for (const [k, n] of counts) {
|
|
136
|
+
if (n > bestN) {
|
|
137
|
+
bestN = n;
|
|
138
|
+
best = k;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return best;
|
|
142
|
+
}
|
|
143
|
+
function openingOf(commits) {
|
|
144
|
+
// Use the first commit's subject as the opening sentence
|
|
145
|
+
const first = commits[0];
|
|
146
|
+
const author = first.authorName || first.authorEmail.split("@")[0] || "the team";
|
|
147
|
+
return `On **${first.authorDate.slice(0, 10)}**, ${author} began with: *"${truncate(first.subject, 120)}"*. ${commits.length} commits would follow over ${humanSpan(commits)}.`;
|
|
148
|
+
}
|
|
149
|
+
function closingOf(commits) {
|
|
150
|
+
const last = commits[commits.length - 1];
|
|
151
|
+
return `By **${last.authorDate.slice(0, 10)}**, the chapter closed with *"${truncate(last.subject, 120)}"*.`;
|
|
152
|
+
}
|
|
153
|
+
function humanSpan(commits) {
|
|
154
|
+
if (commits.length < 2)
|
|
155
|
+
return "a single day";
|
|
156
|
+
const first = new Date(commits[0].authorDate).getTime();
|
|
157
|
+
const last = new Date(commits[commits.length - 1].authorDate).getTime();
|
|
158
|
+
const days = Math.max(1, Math.round((last - first) / 86_400_000));
|
|
159
|
+
if (days < 30)
|
|
160
|
+
return `${days} day${days === 1 ? "" : "s"}`;
|
|
161
|
+
if (days < 365)
|
|
162
|
+
return `${Math.round(days / 30)} months`;
|
|
163
|
+
return `${(days / 365).toFixed(1)} years`;
|
|
164
|
+
}
|
|
165
|
+
function truncate(s, n) {
|
|
166
|
+
const oneLine = s.replace(/\s+/g, " ").trim();
|
|
167
|
+
return oneLine.length <= n ? oneLine : oneLine.slice(0, n - 1).trimEnd() + "…";
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=chronicle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chronicle.js","sourceRoot":"","sources":["../../src/insights/chronicle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chronicle.test.d.ts","sourceRoot":"","sources":["../../src/insights/chronicle.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { buildChronicle, renderChronicle } from "./chronicle.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.author ?? "alice").toLowerCase() + "@example.com",
|
|
9
|
+
authorDate: p.date,
|
|
10
|
+
committerDate: p.date,
|
|
11
|
+
subject: p.subject,
|
|
12
|
+
body: p.body ?? "",
|
|
13
|
+
files: [],
|
|
14
|
+
parents: [],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
describe("buildChronicle", () => {
|
|
18
|
+
it("returns empty chronicle when no commits", () => {
|
|
19
|
+
const c = buildChronicle([]);
|
|
20
|
+
expect(c.totalCommits).toBe(0);
|
|
21
|
+
expect(c.chapters).toHaveLength(0);
|
|
22
|
+
});
|
|
23
|
+
it("creates a single chapter from contiguous commits", () => {
|
|
24
|
+
const commits = Array.from({ length: 8 }, (_, i) => mk({ hash: `c${i}`, date: `2024-01-${(i + 1).toString().padStart(2, "0")}`, subject: `feat: x${i}` }));
|
|
25
|
+
const c = buildChronicle(commits, { gapDays: 30 });
|
|
26
|
+
expect(c.chapters.length).toBe(1);
|
|
27
|
+
expect(c.chapters[0].commits.length).toBe(8);
|
|
28
|
+
});
|
|
29
|
+
it("splits chapters at long gaps (>= gapDays)", () => {
|
|
30
|
+
const commits = [
|
|
31
|
+
...Array.from({ length: 6 }, (_, i) => mk({ hash: `a${i}`, date: `2024-01-${(i + 1).toString().padStart(2, "0")}`, subject: `feat: x${i}` })),
|
|
32
|
+
...Array.from({ length: 6 }, (_, i) => mk({ hash: `b${i}`, date: `2024-08-${(i + 1).toString().padStart(2, "0")}`, subject: `refactor: y${i}` })),
|
|
33
|
+
];
|
|
34
|
+
const c = buildChronicle(commits, { gapDays: 30, minChapterCommits: 3 });
|
|
35
|
+
expect(c.chapters.length).toBeGreaterThanOrEqual(2);
|
|
36
|
+
});
|
|
37
|
+
it("first chapter is always titled 'The Founding'", () => {
|
|
38
|
+
const commits = Array.from({ length: 5 }, (_, i) => mk({ hash: `c${i}`, date: `2024-01-${(i + 1).toString().padStart(2, "0")}`, subject: `init x${i}` }));
|
|
39
|
+
const c = buildChronicle(commits);
|
|
40
|
+
expect(c.chapters[0].title).toBe("The Founding");
|
|
41
|
+
});
|
|
42
|
+
it("titles a refactor-heavy chapter as 'The Great Refactor'", () => {
|
|
43
|
+
const commits = [
|
|
44
|
+
...Array.from({ length: 5 }, (_, i) => mk({ hash: `a${i}`, date: `2024-01-${(i + 1).toString().padStart(2, "0")}`, subject: `feat: x${i}` })),
|
|
45
|
+
...Array.from({ length: 5 }, (_, i) => mk({ hash: `b${i}`, date: `2024-06-${(i + 1).toString().padStart(2, "0")}`, subject: `rewrite parser ${i}` })),
|
|
46
|
+
];
|
|
47
|
+
const c = buildChronicle(commits, { gapDays: 30, minChapterCommits: 3 });
|
|
48
|
+
const refactorChapter = c.chapters.find((ch) => ch.title === "The Great Refactor");
|
|
49
|
+
expect(refactorChapter).toBeDefined();
|
|
50
|
+
});
|
|
51
|
+
it("protagonist is the most-frequent author of the chapter", () => {
|
|
52
|
+
const commits = [
|
|
53
|
+
mk({ hash: "a1", date: "2024-01-01", subject: "x", author: "Alice" }),
|
|
54
|
+
mk({ hash: "a2", date: "2024-01-02", subject: "x", author: "Alice" }),
|
|
55
|
+
mk({ hash: "b1", date: "2024-01-03", subject: "x", author: "Bob" }),
|
|
56
|
+
];
|
|
57
|
+
const c = buildChronicle(commits);
|
|
58
|
+
expect(c.chapters[0].protagonist).toBe("Alice");
|
|
59
|
+
});
|
|
60
|
+
it("opening references the first commit's subject", () => {
|
|
61
|
+
const commits = [
|
|
62
|
+
mk({ hash: "a1", date: "2024-01-01", subject: "Initial scaffold of payment service" }),
|
|
63
|
+
mk({ hash: "a2", date: "2024-01-02", subject: "x" }),
|
|
64
|
+
];
|
|
65
|
+
const c = buildChronicle(commits);
|
|
66
|
+
expect(c.chapters[0].opening).toContain("Initial scaffold of payment service");
|
|
67
|
+
});
|
|
68
|
+
it("renderChronicle produces valid markdown with chapter headings", () => {
|
|
69
|
+
const commits = Array.from({ length: 5 }, (_, i) => mk({ hash: `c${i}`, date: `2024-01-${(i + 1).toString().padStart(2, "0")}`, subject: `feat: x${i}` }));
|
|
70
|
+
const c = buildChronicle(commits);
|
|
71
|
+
const md = renderChronicle(c);
|
|
72
|
+
expect(md).toContain("# Chronicles of Your Codebase");
|
|
73
|
+
expect(md).toMatch(/## Chapter 1 ·/);
|
|
74
|
+
expect(md).toContain("**2024-01-01");
|
|
75
|
+
});
|
|
76
|
+
it("renderChronicle handles empty chronicle gracefully", () => {
|
|
77
|
+
const md = renderChronicle({ totalCommits: 0, totalDays: 0, chapters: [] });
|
|
78
|
+
expect(md).toContain("No commits to chronicle yet");
|
|
79
|
+
});
|
|
80
|
+
it("chapter dates are in chronological order", () => {
|
|
81
|
+
const commits = [
|
|
82
|
+
mk({ hash: "a1", date: "2024-01-01", subject: "x" }),
|
|
83
|
+
mk({ hash: "a2", date: "2024-02-01", subject: "x" }),
|
|
84
|
+
mk({ hash: "a3", date: "2024-03-01", subject: "x" }),
|
|
85
|
+
];
|
|
86
|
+
const c = buildChronicle(commits, { gapDays: 1, minChapterCommits: 1 });
|
|
87
|
+
for (let i = 1; i < c.chapters.length; i++) {
|
|
88
|
+
expect(c.chapters[i - 1].fromDate.localeCompare(c.chapters[i].fromDate)).toBeLessThanOrEqual(0);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=chronicle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chronicle.test.js","sourceRoot":"","sources":["../../src/insights/chronicle.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mneme constellation` — build a graph view of the codebase as a living
|
|
3
|
+
* map: files are stars, authors are orbital bodies, edges are co-edits
|
|
4
|
+
* (file↔file) and authorships (file↔author).
|
|
5
|
+
*
|
|
6
|
+
* v0.12 ships the graph extraction + JSON export + ASCII summary. A web
|
|
7
|
+
* UI (`mneme constellation --serve` for a 3D WebGL viewer) is on the
|
|
8
|
+
* roadmap; the graph data is the underlying truth either way.
|
|
9
|
+
*
|
|
10
|
+
* Pure data extraction. No external services. No 3D rendering here —
|
|
11
|
+
* just the graph the renderer needs.
|
|
12
|
+
*/
|
|
13
|
+
import type { Commit } from "../types.js";
|
|
14
|
+
export interface FileStar {
|
|
15
|
+
filePath: string;
|
|
16
|
+
/** Total times the file was committed in window. */
|
|
17
|
+
weight: number;
|
|
18
|
+
/** Last touched ISO date. */
|
|
19
|
+
lastTouched: string;
|
|
20
|
+
/** Top-level directory — useful for clustering / coloring. */
|
|
21
|
+
cluster: string;
|
|
22
|
+
}
|
|
23
|
+
export interface AuthorOrbital {
|
|
24
|
+
author: string;
|
|
25
|
+
/** Total commits in window. */
|
|
26
|
+
weight: number;
|
|
27
|
+
/** Top files this author "orbits" (by touch share). */
|
|
28
|
+
topFiles: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface FileEdge {
|
|
31
|
+
/** Sorted alphabetically: a < b. */
|
|
32
|
+
fileA: string;
|
|
33
|
+
fileB: string;
|
|
34
|
+
/** Number of commits that touched both files together. */
|
|
35
|
+
coEdits: number;
|
|
36
|
+
}
|
|
37
|
+
export interface AuthorshipEdge {
|
|
38
|
+
author: string;
|
|
39
|
+
filePath: string;
|
|
40
|
+
touches: number;
|
|
41
|
+
}
|
|
42
|
+
export interface Constellation {
|
|
43
|
+
windowCommits: number;
|
|
44
|
+
fileStars: FileStar[];
|
|
45
|
+
authorOrbitals: AuthorOrbital[];
|
|
46
|
+
fileEdges: FileEdge[];
|
|
47
|
+
authorshipEdges: AuthorshipEdge[];
|
|
48
|
+
/** Number of distinct top-level clusters (directories) detected. */
|
|
49
|
+
clusterCount: number;
|
|
50
|
+
}
|
|
51
|
+
export declare function buildConstellation(commits: Commit[], opts?: {
|
|
52
|
+
minFileTouches?: number;
|
|
53
|
+
minAuthorCommits?: number;
|
|
54
|
+
maxFileEdges?: number;
|
|
55
|
+
maxStars?: number;
|
|
56
|
+
maxOrbitals?: number;
|
|
57
|
+
}): Constellation;
|
|
58
|
+
/**
|
|
59
|
+
* Render an ASCII summary suitable for terminal output. The web UI will
|
|
60
|
+
* consume the JSON directly via `--json`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function renderConstellationAscii(c: Constellation, topN?: number): string;
|
|
63
|
+
//# sourceMappingURL=constellation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constellation.d.ts","sourceRoot":"","sources":["../../src/insights/constellation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IACJ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACjB,GACL,aAAa,CAgHf;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,SAAI,GAAG,MAAM,CAsB3E"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
export function buildConstellation(commits, opts = {}) {
|
|
2
|
+
const minFileTouches = opts.minFileTouches ?? 2;
|
|
3
|
+
const minAuthorCommits = opts.minAuthorCommits ?? 2;
|
|
4
|
+
const maxFileEdges = opts.maxFileEdges ?? 200;
|
|
5
|
+
const maxStars = opts.maxStars ?? 200;
|
|
6
|
+
const maxOrbitals = opts.maxOrbitals ?? 30;
|
|
7
|
+
// file → { weight, lastTouched }
|
|
8
|
+
const filesMap = new Map();
|
|
9
|
+
// author → { weight, topFiles map }
|
|
10
|
+
const authorsMap = new Map();
|
|
11
|
+
// co-edit map: "a||b" → coEdits
|
|
12
|
+
const coEditMap = new Map();
|
|
13
|
+
// authorship: "author||file" → touches
|
|
14
|
+
const authorshipMap = new Map();
|
|
15
|
+
for (const c of commits) {
|
|
16
|
+
const files = c.files;
|
|
17
|
+
const author = c.authorName || c.authorEmail;
|
|
18
|
+
// bump file weight
|
|
19
|
+
for (const f of files) {
|
|
20
|
+
let fr = filesMap.get(f);
|
|
21
|
+
if (!fr) {
|
|
22
|
+
fr = { weight: 0, lastTouched: c.authorDate };
|
|
23
|
+
filesMap.set(f, fr);
|
|
24
|
+
}
|
|
25
|
+
fr.weight += 1;
|
|
26
|
+
if (c.authorDate.localeCompare(fr.lastTouched) > 0) {
|
|
27
|
+
fr.lastTouched = c.authorDate;
|
|
28
|
+
}
|
|
29
|
+
// authorship edge
|
|
30
|
+
const akey = `${author}||${f}`;
|
|
31
|
+
let ae = authorshipMap.get(akey);
|
|
32
|
+
if (!ae) {
|
|
33
|
+
ae = { author, filePath: f, touches: 0 };
|
|
34
|
+
authorshipMap.set(akey, ae);
|
|
35
|
+
}
|
|
36
|
+
ae.touches += 1;
|
|
37
|
+
// author orbital weight
|
|
38
|
+
let ar = authorsMap.get(author);
|
|
39
|
+
if (!ar) {
|
|
40
|
+
ar = { weight: 0, files: new Map() };
|
|
41
|
+
authorsMap.set(author, ar);
|
|
42
|
+
}
|
|
43
|
+
ar.weight += 1;
|
|
44
|
+
ar.files.set(f, (ar.files.get(f) ?? 0) + 1);
|
|
45
|
+
}
|
|
46
|
+
// co-edit edges (every pair of files in a commit)
|
|
47
|
+
for (let i = 0; i < files.length; i++) {
|
|
48
|
+
for (let j = i + 1; j < files.length; j++) {
|
|
49
|
+
const a = files[i];
|
|
50
|
+
const b = files[j];
|
|
51
|
+
const [x, y] = a < b ? [a, b] : [b, a];
|
|
52
|
+
const key = `${x}||${y}`;
|
|
53
|
+
coEditMap.set(key, (coEditMap.get(key) ?? 0) + 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Build file stars (filtered + capped)
|
|
58
|
+
const fileStars = [];
|
|
59
|
+
for (const [filePath, info] of filesMap) {
|
|
60
|
+
if (info.weight < minFileTouches)
|
|
61
|
+
continue;
|
|
62
|
+
fileStars.push({
|
|
63
|
+
filePath,
|
|
64
|
+
weight: info.weight,
|
|
65
|
+
lastTouched: info.lastTouched.slice(0, 10),
|
|
66
|
+
cluster: filePath.split("/").slice(0, 2).join("/") || "(root)",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
fileStars.sort((a, b) => b.weight - a.weight);
|
|
70
|
+
if (fileStars.length > maxStars)
|
|
71
|
+
fileStars.length = maxStars;
|
|
72
|
+
// Build orbitals (filtered + capped)
|
|
73
|
+
const authorOrbitals = [];
|
|
74
|
+
for (const [author, info] of authorsMap) {
|
|
75
|
+
if (info.weight < minAuthorCommits)
|
|
76
|
+
continue;
|
|
77
|
+
const topFiles = [...info.files.entries()]
|
|
78
|
+
.sort((a, b) => b[1] - a[1])
|
|
79
|
+
.slice(0, 5)
|
|
80
|
+
.map(([f]) => f);
|
|
81
|
+
authorOrbitals.push({ author, weight: info.weight, topFiles });
|
|
82
|
+
}
|
|
83
|
+
authorOrbitals.sort((a, b) => b.weight - a.weight);
|
|
84
|
+
if (authorOrbitals.length > maxOrbitals)
|
|
85
|
+
authorOrbitals.length = maxOrbitals;
|
|
86
|
+
// Build file edges (top by coEdits)
|
|
87
|
+
const allFileEdges = [];
|
|
88
|
+
for (const [key, n] of coEditMap) {
|
|
89
|
+
if (n < 2)
|
|
90
|
+
continue;
|
|
91
|
+
const [a, b] = key.split("||");
|
|
92
|
+
allFileEdges.push({ fileA: a, fileB: b, coEdits: n });
|
|
93
|
+
}
|
|
94
|
+
allFileEdges.sort((a, b) => b.coEdits - a.coEdits);
|
|
95
|
+
const fileEdges = allFileEdges.slice(0, maxFileEdges);
|
|
96
|
+
// Build authorship edges
|
|
97
|
+
const authorshipEdges = [...authorshipMap.values()]
|
|
98
|
+
.filter((e) => e.touches >= minFileTouches)
|
|
99
|
+
.sort((a, b) => b.touches - a.touches);
|
|
100
|
+
// Cluster count
|
|
101
|
+
const clusters = new Set(fileStars.map((s) => s.cluster));
|
|
102
|
+
return {
|
|
103
|
+
windowCommits: commits.length,
|
|
104
|
+
fileStars,
|
|
105
|
+
authorOrbitals,
|
|
106
|
+
fileEdges,
|
|
107
|
+
authorshipEdges,
|
|
108
|
+
clusterCount: clusters.size,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Render an ASCII summary suitable for terminal output. The web UI will
|
|
113
|
+
* consume the JSON directly via `--json`.
|
|
114
|
+
*/
|
|
115
|
+
export function renderConstellationAscii(c, topN = 8) {
|
|
116
|
+
const lines = [];
|
|
117
|
+
lines.push("");
|
|
118
|
+
lines.push(` ${c.fileStars.length} file-stars · ${c.authorOrbitals.length} orbitals · ${c.fileEdges.length} co-edit edges · ${c.clusterCount} clusters`);
|
|
119
|
+
lines.push("");
|
|
120
|
+
lines.push(" ◆ Brightest stars (most-touched files)");
|
|
121
|
+
for (const s of c.fileStars.slice(0, topN)) {
|
|
122
|
+
const meter = bar(s.weight, c.fileStars[0]?.weight ?? 1);
|
|
123
|
+
lines.push(` ${meter} ${s.filePath} (${s.weight}×)`);
|
|
124
|
+
}
|
|
125
|
+
lines.push("");
|
|
126
|
+
lines.push(" ◆ Closest orbitals (most-active authors)");
|
|
127
|
+
for (const o of c.authorOrbitals.slice(0, topN)) {
|
|
128
|
+
const meter = bar(o.weight, c.authorOrbitals[0]?.weight ?? 1);
|
|
129
|
+
lines.push(` ${meter} ${o.author} (${o.weight} commits)`);
|
|
130
|
+
}
|
|
131
|
+
lines.push("");
|
|
132
|
+
lines.push(" ◆ Strongest co-edit edges (files often committed together)");
|
|
133
|
+
for (const e of c.fileEdges.slice(0, topN)) {
|
|
134
|
+
lines.push(` ${e.coEdits}× ${shorten(e.fileA, 35)} ⟷ ${shorten(e.fileB, 35)}`);
|
|
135
|
+
}
|
|
136
|
+
return lines.join("\n");
|
|
137
|
+
}
|
|
138
|
+
function bar(value, max, width = 8) {
|
|
139
|
+
if (max <= 0)
|
|
140
|
+
return " ".repeat(width);
|
|
141
|
+
const blocks = Math.max(0, Math.min(width, Math.round((value / max) * width)));
|
|
142
|
+
return "█".repeat(blocks) + "░".repeat(width - blocks);
|
|
143
|
+
}
|
|
144
|
+
function shorten(s, n) {
|
|
145
|
+
return s.length <= n ? s : "…" + s.slice(s.length - n + 1);
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=constellation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constellation.js","sourceRoot":"","sources":["../../src/insights/constellation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constellation.test.d.ts","sourceRoot":"","sources":["../../src/insights/constellation.test.ts"],"names":[],"mappings":""}
|