@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.
- 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/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/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/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 +9 -0
- package/dist/insights/index.d.ts.map +1 -1
- package/dist/insights/index.js +9 -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/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,170 @@
|
|
|
1
|
+
const FEATURE_RE = /\b(feat|feature|add|implement|introduce|support|expose)\b/i;
|
|
2
|
+
const REFACTOR_RE = /\b(refactor|rewrite|migrate|switch(?:ed)? to|extract|consolidate|simplify)\b/i;
|
|
3
|
+
const FIRE_RE = /\b(fix|hotfix|revert|rollback|broken|crash|regression|emergency|urgent|critical)\b/i;
|
|
4
|
+
const POLISH_RE = /\b(typo|format|lint|rename|comment|whitespace|cleanup|chore|polish|tighten)\b/i;
|
|
5
|
+
const DOCS_RE = /\b(docs?|readme|comment|documentation)\b/i;
|
|
6
|
+
const KINDS = ["feature", "refactor", "firefight", "polish", "docs", "other"];
|
|
7
|
+
export function classifyCommit(c) {
|
|
8
|
+
const text = `${c.subject}\n${c.body || ""}`;
|
|
9
|
+
if (FIRE_RE.test(text))
|
|
10
|
+
return "firefight";
|
|
11
|
+
if (REFACTOR_RE.test(text))
|
|
12
|
+
return "refactor";
|
|
13
|
+
if (FEATURE_RE.test(text))
|
|
14
|
+
return "feature";
|
|
15
|
+
if (DOCS_RE.test(text))
|
|
16
|
+
return "docs";
|
|
17
|
+
if (POLISH_RE.test(text))
|
|
18
|
+
return "polish";
|
|
19
|
+
return "other";
|
|
20
|
+
}
|
|
21
|
+
export function buildDrift(commits, opts = {}) {
|
|
22
|
+
const granularity = opts.granularity ?? "quarter";
|
|
23
|
+
const sorted = [...commits].sort((a, b) => a.authorDate.localeCompare(b.authorDate));
|
|
24
|
+
if (sorted.length === 0) {
|
|
25
|
+
return { granularity, buckets: [], insights: [] };
|
|
26
|
+
}
|
|
27
|
+
const buckets = new Map();
|
|
28
|
+
for (const c of sorted) {
|
|
29
|
+
const label = labelOf(c.authorDate, granularity);
|
|
30
|
+
const range = rangeOf(label, granularity);
|
|
31
|
+
let b = buckets.get(label);
|
|
32
|
+
if (!b) {
|
|
33
|
+
b = {
|
|
34
|
+
label,
|
|
35
|
+
fromDate: range.from,
|
|
36
|
+
toDate: range.to,
|
|
37
|
+
total: 0,
|
|
38
|
+
byKind: { feature: 0, refactor: 0, firefight: 0, polish: 0, docs: 0, other: 0 },
|
|
39
|
+
dominant: "other",
|
|
40
|
+
};
|
|
41
|
+
buckets.set(label, b);
|
|
42
|
+
}
|
|
43
|
+
const k = classifyCommit(c);
|
|
44
|
+
b.byKind[k] += 1;
|
|
45
|
+
b.total += 1;
|
|
46
|
+
}
|
|
47
|
+
// resolve dominant
|
|
48
|
+
for (const b of buckets.values()) {
|
|
49
|
+
let best = "other";
|
|
50
|
+
let bestN = -1;
|
|
51
|
+
for (const k of KINDS) {
|
|
52
|
+
const n = b.byKind[k];
|
|
53
|
+
if (n > bestN) {
|
|
54
|
+
bestN = n;
|
|
55
|
+
best = k;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
b.dominant = best;
|
|
59
|
+
}
|
|
60
|
+
const ordered = [...buckets.values()].sort((a, b) => a.fromDate.localeCompare(b.fromDate));
|
|
61
|
+
return {
|
|
62
|
+
granularity,
|
|
63
|
+
buckets: ordered,
|
|
64
|
+
insights: detectInsights(ordered),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function detectInsights(buckets) {
|
|
68
|
+
const out = [];
|
|
69
|
+
if (buckets.length < 2)
|
|
70
|
+
return out;
|
|
71
|
+
// Burnout: firefight ratio rises ≥ 30 percentage points across 2+ adjacent buckets.
|
|
72
|
+
for (let i = 1; i < buckets.length; i++) {
|
|
73
|
+
const prev = buckets[i - 1];
|
|
74
|
+
const cur = buckets[i];
|
|
75
|
+
const prevFire = ratio(prev.byKind.firefight, prev.total);
|
|
76
|
+
const curFire = ratio(cur.byKind.firefight, cur.total);
|
|
77
|
+
if (curFire - prevFire >= 0.3 && cur.total >= 5) {
|
|
78
|
+
out.push({
|
|
79
|
+
kind: "burnout",
|
|
80
|
+
fromBucket: prev.label,
|
|
81
|
+
toBucket: cur.label,
|
|
82
|
+
description: `firefight ratio jumped from ${pct(prevFire)} to ${pct(curFire)} — possible incident streak or burnout signal.`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (prevFire >= 0.4 && curFire < prevFire - 0.2) {
|
|
86
|
+
out.push({
|
|
87
|
+
kind: "recovery",
|
|
88
|
+
fromBucket: prev.label,
|
|
89
|
+
toBucket: cur.label,
|
|
90
|
+
description: `firefight ratio fell from ${pct(prevFire)} to ${pct(curFire)} — repo stabilizing.`,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Rewrite cluster: 2+ adjacent buckets where dominant = refactor
|
|
95
|
+
for (let i = 0; i < buckets.length - 1; i++) {
|
|
96
|
+
if (buckets[i].dominant === "refactor" && buckets[i + 1].dominant === "refactor") {
|
|
97
|
+
out.push({
|
|
98
|
+
kind: "rewrite-cluster",
|
|
99
|
+
fromBucket: buckets[i].label,
|
|
100
|
+
toBucket: buckets[i + 1].label,
|
|
101
|
+
description: `consecutive periods dominated by refactors — major restructuring effort.`,
|
|
102
|
+
});
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Polish streak: 3+ adjacent buckets dominated by polish or docs
|
|
107
|
+
let polishRun = 0;
|
|
108
|
+
let polishStart = "";
|
|
109
|
+
for (const b of buckets) {
|
|
110
|
+
if (b.dominant === "polish" || b.dominant === "docs") {
|
|
111
|
+
if (polishRun === 0)
|
|
112
|
+
polishStart = b.label;
|
|
113
|
+
polishRun++;
|
|
114
|
+
if (polishRun >= 3) {
|
|
115
|
+
out.push({
|
|
116
|
+
kind: "polish-streak",
|
|
117
|
+
fromBucket: polishStart,
|
|
118
|
+
toBucket: b.label,
|
|
119
|
+
description: `${polishRun} consecutive periods of polish/docs — mature, stable phase.`,
|
|
120
|
+
});
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
polishRun = 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
function ratio(num, denom) {
|
|
131
|
+
return denom === 0 ? 0 : num / denom;
|
|
132
|
+
}
|
|
133
|
+
function pct(r) {
|
|
134
|
+
return `${Math.round(r * 100)}%`;
|
|
135
|
+
}
|
|
136
|
+
function labelOf(iso, gran) {
|
|
137
|
+
const d = new Date(iso);
|
|
138
|
+
if (Number.isNaN(d.getTime()))
|
|
139
|
+
return "unknown";
|
|
140
|
+
const y = d.getUTCFullYear();
|
|
141
|
+
const m = d.getUTCMonth(); // 0..11
|
|
142
|
+
if (gran === "month") {
|
|
143
|
+
return `${y}-${String(m + 1).padStart(2, "0")}`;
|
|
144
|
+
}
|
|
145
|
+
const q = Math.floor(m / 3) + 1;
|
|
146
|
+
return `${y}-Q${q}`;
|
|
147
|
+
}
|
|
148
|
+
function rangeOf(label, gran) {
|
|
149
|
+
if (gran === "month") {
|
|
150
|
+
const [y, m] = label.split("-");
|
|
151
|
+
const ynum = Number(y);
|
|
152
|
+
const mnum = Number(m);
|
|
153
|
+
const last = new Date(Date.UTC(ynum, mnum, 0));
|
|
154
|
+
return {
|
|
155
|
+
from: `${y}-${m}-01`,
|
|
156
|
+
to: `${y}-${m}-${String(last.getUTCDate()).padStart(2, "0")}`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
// quarter
|
|
160
|
+
const [y, qstr] = label.split("-Q");
|
|
161
|
+
const q = Number(qstr);
|
|
162
|
+
const startMonth = (q - 1) * 3 + 1;
|
|
163
|
+
const endMonth = startMonth + 2;
|
|
164
|
+
const last = new Date(Date.UTC(Number(y), endMonth, 0));
|
|
165
|
+
return {
|
|
166
|
+
from: `${y}-${String(startMonth).padStart(2, "0")}-01`,
|
|
167
|
+
to: `${y}-${String(endMonth).padStart(2, "0")}-${String(last.getUTCDate()).padStart(2, "0")}`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=drift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/insights/drift.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift.test.d.ts","sourceRoot":"","sources":["../../src/insights/drift.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { buildDrift, classifyCommit } from "./drift.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,
|
|
10
|
+
committerDate: p.date,
|
|
11
|
+
subject: p.subject,
|
|
12
|
+
body: p.body ?? "",
|
|
13
|
+
files: [],
|
|
14
|
+
parents: [],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
describe("classifyCommit", () => {
|
|
18
|
+
it("classifies firefight from fix/hotfix/revert keywords", () => {
|
|
19
|
+
expect(classifyCommit(mk({ hash: "a", date: "2024-01-01", subject: "fix bug" }))).toBe("firefight");
|
|
20
|
+
expect(classifyCommit(mk({ hash: "b", date: "2024-01-01", subject: "hotfix critical" }))).toBe("firefight");
|
|
21
|
+
expect(classifyCommit(mk({ hash: "c", date: "2024-01-01", subject: "revert bad change" }))).toBe("firefight");
|
|
22
|
+
});
|
|
23
|
+
it("classifies refactor from rewrite/migrate keywords", () => {
|
|
24
|
+
expect(classifyCommit(mk({ hash: "a", date: "2024-01-01", subject: "refactor handler" }))).toBe("refactor");
|
|
25
|
+
expect(classifyCommit(mk({ hash: "b", date: "2024-01-01", subject: "rewrite parser" }))).toBe("refactor");
|
|
26
|
+
expect(classifyCommit(mk({ hash: "c", date: "2024-01-01", subject: "migrate to v3" }))).toBe("refactor");
|
|
27
|
+
});
|
|
28
|
+
it("classifies feature from feat/add/implement keywords", () => {
|
|
29
|
+
expect(classifyCommit(mk({ hash: "a", date: "2024-01-01", subject: "feat: add caching" }))).toBe("feature");
|
|
30
|
+
expect(classifyCommit(mk({ hash: "b", date: "2024-01-01", subject: "add new endpoint" }))).toBe("feature");
|
|
31
|
+
expect(classifyCommit(mk({ hash: "c", date: "2024-01-01", subject: "implement OAuth" }))).toBe("feature");
|
|
32
|
+
});
|
|
33
|
+
it("classifies polish from chore/typo/format keywords", () => {
|
|
34
|
+
expect(classifyCommit(mk({ hash: "a", date: "2024-01-01", subject: "chore: reformat" }))).toBe("polish");
|
|
35
|
+
expect(classifyCommit(mk({ hash: "b", date: "2024-01-01", subject: "fix typo in README" }))).toBe("firefight");
|
|
36
|
+
});
|
|
37
|
+
it("falls back to 'other' for ambiguous subjects", () => {
|
|
38
|
+
expect(classifyCommit(mk({ hash: "a", date: "2024-01-01", subject: "merge branch" }))).toBe("other");
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe("buildDrift", () => {
|
|
42
|
+
it("returns empty report for empty input", () => {
|
|
43
|
+
const r = buildDrift([]);
|
|
44
|
+
expect(r.buckets).toHaveLength(0);
|
|
45
|
+
expect(r.insights).toHaveLength(0);
|
|
46
|
+
});
|
|
47
|
+
it("groups commits into quarter buckets by default", () => {
|
|
48
|
+
const commits = [
|
|
49
|
+
mk({ hash: "a1", date: "2024-01-15", subject: "feat: x" }),
|
|
50
|
+
mk({ hash: "a2", date: "2024-04-15", subject: "feat: y" }),
|
|
51
|
+
mk({ hash: "a3", date: "2024-08-15", subject: "feat: z" }),
|
|
52
|
+
];
|
|
53
|
+
const r = buildDrift(commits);
|
|
54
|
+
expect(r.granularity).toBe("quarter");
|
|
55
|
+
expect(r.buckets.length).toBe(3);
|
|
56
|
+
expect(r.buckets[0].label).toBe("2024-Q1");
|
|
57
|
+
expect(r.buckets[1].label).toBe("2024-Q2");
|
|
58
|
+
expect(r.buckets[2].label).toBe("2024-Q3");
|
|
59
|
+
});
|
|
60
|
+
it("supports month granularity", () => {
|
|
61
|
+
const commits = [
|
|
62
|
+
mk({ hash: "a1", date: "2024-01-15", subject: "x" }),
|
|
63
|
+
mk({ hash: "a2", date: "2024-02-15", subject: "y" }),
|
|
64
|
+
];
|
|
65
|
+
const r = buildDrift(commits, { granularity: "month" });
|
|
66
|
+
expect(r.granularity).toBe("month");
|
|
67
|
+
expect(r.buckets[0].label).toBe("2024-01");
|
|
68
|
+
expect(r.buckets[1].label).toBe("2024-02");
|
|
69
|
+
});
|
|
70
|
+
it("dominant kind is the highest-count category in a bucket", () => {
|
|
71
|
+
const commits = [
|
|
72
|
+
mk({ hash: "a1", date: "2024-01-01", subject: "fix bug 1" }),
|
|
73
|
+
mk({ hash: "a2", date: "2024-01-02", subject: "fix bug 2" }),
|
|
74
|
+
mk({ hash: "a3", date: "2024-01-03", subject: "feat: add x" }),
|
|
75
|
+
];
|
|
76
|
+
const r = buildDrift(commits);
|
|
77
|
+
expect(r.buckets[0].dominant).toBe("firefight");
|
|
78
|
+
});
|
|
79
|
+
it("detects burnout insight when firefight ratio jumps", () => {
|
|
80
|
+
const commits = [];
|
|
81
|
+
// Q1: 5 features
|
|
82
|
+
for (let i = 0; i < 5; i++) {
|
|
83
|
+
commits.push(mk({ hash: `f${i}`, date: `2024-01-${(i + 1).toString().padStart(2, "0")}`, subject: `feat: x${i}` }));
|
|
84
|
+
}
|
|
85
|
+
// Q2: 5 fires
|
|
86
|
+
for (let i = 0; i < 5; i++) {
|
|
87
|
+
commits.push(mk({ hash: `b${i}`, date: `2024-04-${(i + 1).toString().padStart(2, "0")}`, subject: `fix bug ${i}` }));
|
|
88
|
+
}
|
|
89
|
+
const r = buildDrift(commits);
|
|
90
|
+
expect(r.insights.some((i) => i.kind === "burnout")).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
it("detects recovery insight when firefight ratio falls", () => {
|
|
93
|
+
const commits = [];
|
|
94
|
+
for (let i = 0; i < 5; i++) {
|
|
95
|
+
commits.push(mk({ hash: `b${i}`, date: `2024-01-${(i + 1).toString().padStart(2, "0")}`, subject: `fix bug ${i}` }));
|
|
96
|
+
}
|
|
97
|
+
for (let i = 0; i < 5; i++) {
|
|
98
|
+
commits.push(mk({ hash: `f${i}`, date: `2024-04-${(i + 1).toString().padStart(2, "0")}`, subject: `feat: nice thing ${i}` }));
|
|
99
|
+
}
|
|
100
|
+
const r = buildDrift(commits);
|
|
101
|
+
expect(r.insights.some((i) => i.kind === "recovery")).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
it("detects rewrite cluster across consecutive quarters", () => {
|
|
104
|
+
const commits = [];
|
|
105
|
+
for (let i = 0; i < 4; i++) {
|
|
106
|
+
commits.push(mk({ hash: `r${i}`, date: `2024-01-${(i + 1).toString().padStart(2, "0")}`, subject: `refactor module ${i}` }));
|
|
107
|
+
}
|
|
108
|
+
for (let i = 0; i < 4; i++) {
|
|
109
|
+
commits.push(mk({ hash: `s${i}`, date: `2024-04-${(i + 1).toString().padStart(2, "0")}`, subject: `rewrite component ${i}` }));
|
|
110
|
+
}
|
|
111
|
+
const r = buildDrift(commits);
|
|
112
|
+
expect(r.insights.some((i) => i.kind === "rewrite-cluster")).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
it("orders buckets chronologically by fromDate", () => {
|
|
115
|
+
const commits = [
|
|
116
|
+
mk({ hash: "a3", date: "2025-01-15", subject: "x" }),
|
|
117
|
+
mk({ hash: "a1", date: "2024-01-15", subject: "x" }),
|
|
118
|
+
mk({ hash: "a2", date: "2024-04-15", subject: "x" }),
|
|
119
|
+
];
|
|
120
|
+
const r = buildDrift(commits);
|
|
121
|
+
for (let i = 1; i < r.buckets.length; i++) {
|
|
122
|
+
expect(r.buckets[i - 1].fromDate.localeCompare(r.buckets[i].fromDate)).toBeLessThan(0);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=drift.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift.test.js","sourceRoot":"","sources":["../../src/insights/drift.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGxD,SAAS,EAAE,CAAC,CAAiE;IAC3E,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7B,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE,SAAS;QACtB,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,EAAE;QACT,OAAO,EAAE,EAAE;KACZ,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACpG,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5G,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAChH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5G,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1G,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5G,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3G,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzG,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;YAC1D,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;YAC1D,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;SAC3D,CAAC;QACF,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YACpD,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;SACrD,CAAC;QACF,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;YAC5D,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;YAC5D,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;SAC/D,CAAC;QACF,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,iBAAiB;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACtH,CAAC;QACD,cAAc;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACvH,CAAC;QACD,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACvH,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,oBAAoB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAChI,CAAC;QACD,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,mBAAmB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/H,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,qBAAqB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACjI,CAAC;QACD,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,OAAO,GAAG;YACd,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YACpD,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YACpD,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;SACrD,CAAC;QACF,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -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":""}
|