@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,92 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { buildExportBundle, renderExportMarkdown } from "./export-bundle.js";
|
|
3
|
+
const NOW = new Date("2026-05-05").getTime();
|
|
4
|
+
function mk(p) {
|
|
5
|
+
return {
|
|
6
|
+
hash: p.hash,
|
|
7
|
+
shortHash: p.hash.slice(0, 7),
|
|
8
|
+
authorName: p.author,
|
|
9
|
+
authorEmail: p.author.toLowerCase() + "@x.com",
|
|
10
|
+
authorDate: p.date,
|
|
11
|
+
committerDate: p.date,
|
|
12
|
+
subject: p.subject,
|
|
13
|
+
body: "",
|
|
14
|
+
files: p.files ?? [],
|
|
15
|
+
parents: [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
describe("buildExportBundle", () => {
|
|
19
|
+
it("returns bundle with empty sections for empty commits", () => {
|
|
20
|
+
const b = buildExportBundle([], { nowMs: NOW });
|
|
21
|
+
expect(b.repo.totalCommits).toBe(0);
|
|
22
|
+
expect(b.topAuthorsDna).toHaveLength(0);
|
|
23
|
+
});
|
|
24
|
+
it("includes top author DNA strands", () => {
|
|
25
|
+
const commits = [
|
|
26
|
+
mk({ hash: "a1", date: "2026-04-01", subject: "x", author: "Alice", files: ["x.ts"] }),
|
|
27
|
+
mk({ hash: "a2", date: "2026-04-02", subject: "x", author: "Alice", files: ["x.ts"] }),
|
|
28
|
+
mk({ hash: "b1", date: "2026-04-03", subject: "x", author: "Bob", files: ["x.ts"] }),
|
|
29
|
+
];
|
|
30
|
+
const b = buildExportBundle(commits, { nowMs: NOW, topAuthors: 2 });
|
|
31
|
+
expect(b.topAuthorsDna).toHaveLength(2);
|
|
32
|
+
expect(b.topAuthorsDna[0].author).toBe("alice@x.com");
|
|
33
|
+
});
|
|
34
|
+
it("repo summary reflects commit range", () => {
|
|
35
|
+
const commits = [
|
|
36
|
+
mk({ hash: "a1", date: "2024-01-01", subject: "x", author: "Alice" }),
|
|
37
|
+
mk({ hash: "a2", date: "2025-06-01", subject: "x", author: "Bob" }),
|
|
38
|
+
];
|
|
39
|
+
const b = buildExportBundle(commits);
|
|
40
|
+
expect(b.repo.fromDate).toBe("2024-01-01");
|
|
41
|
+
expect(b.repo.toDate).toBe("2025-06-01");
|
|
42
|
+
expect(b.repo.totalAuthors).toBe(2);
|
|
43
|
+
expect(b.repo.totalCommits).toBe(2);
|
|
44
|
+
});
|
|
45
|
+
it("renderExportMarkdown produces a non-empty document with all sections", () => {
|
|
46
|
+
const commits = Array.from({ length: 8 }, (_, i) => mk({
|
|
47
|
+
hash: `a${i}`,
|
|
48
|
+
date: `2026-04-${(i + 1).toString().padStart(2, "0")}`,
|
|
49
|
+
subject: `feat: x${i}`,
|
|
50
|
+
author: i % 2 === 0 ? "Alice" : "Bob",
|
|
51
|
+
files: [`src/x${i}.ts`],
|
|
52
|
+
}));
|
|
53
|
+
const b = buildExportBundle(commits, { nowMs: NOW });
|
|
54
|
+
const md = renderExportMarkdown(b);
|
|
55
|
+
expect(md).toContain("# Mneme — Codebase Bundle");
|
|
56
|
+
expect(md).toContain("## 📊 Team Health");
|
|
57
|
+
expect(md).toContain("## 📈 Drift trajectory");
|
|
58
|
+
expect(md).toContain("## 📖 Chronicle");
|
|
59
|
+
expect(md).toContain("## 🧬 Top contributors");
|
|
60
|
+
expect(md).toContain("## 🕸 Author network");
|
|
61
|
+
expect(md).toContain("## 🧠 Semantic commit clusters");
|
|
62
|
+
expect(md).toContain("## 🔮 Oracle predictions");
|
|
63
|
+
expect(md).toContain("## 🌌 Constellation");
|
|
64
|
+
expect(md).toContain("## 👻 Ghost code");
|
|
65
|
+
});
|
|
66
|
+
it("bundle includes drift, chronicle, oracle, constellation, clusters, network, manage, ghost", () => {
|
|
67
|
+
const commits = [
|
|
68
|
+
mk({ hash: "a1", date: "2026-04-01", subject: "feat: caching", author: "Alice", files: ["x.ts"] }),
|
|
69
|
+
mk({ hash: "a2", date: "2026-04-02", subject: "feat: caching", author: "Alice", files: ["x.ts"] }),
|
|
70
|
+
mk({ hash: "b1", date: "2026-04-03", subject: "fix bug", author: "Bob", files: ["x.ts"] }),
|
|
71
|
+
];
|
|
72
|
+
const b = buildExportBundle(commits, { nowMs: NOW });
|
|
73
|
+
expect(b.drift).toBeDefined();
|
|
74
|
+
expect(b.chronicle).toBeDefined();
|
|
75
|
+
expect(b.oracle).toBeDefined();
|
|
76
|
+
expect(b.constellation).toBeDefined();
|
|
77
|
+
expect(b.clusters).toBeDefined();
|
|
78
|
+
expect(b.network).toBeDefined();
|
|
79
|
+
expect(b.manage).toBeDefined();
|
|
80
|
+
expect(b.ghost).toBeDefined();
|
|
81
|
+
});
|
|
82
|
+
it("respects topAuthors cap", () => {
|
|
83
|
+
const commits = [
|
|
84
|
+
mk({ hash: "a1", date: "2026-04-01", subject: "x", author: "Alice", files: ["x.ts"] }),
|
|
85
|
+
mk({ hash: "b1", date: "2026-04-02", subject: "x", author: "Bob", files: ["x.ts"] }),
|
|
86
|
+
mk({ hash: "c1", date: "2026-04-03", subject: "x", author: "Carol", files: ["x.ts"] }),
|
|
87
|
+
];
|
|
88
|
+
const b = buildExportBundle(commits, { topAuthors: 2 });
|
|
89
|
+
expect(b.topAuthorsDna.length).toBeLessThanOrEqual(2);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=export-bundle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-bundle.test.js","sourceRoot":"","sources":["../../src/insights/export-bundle.test.ts"],"names":[],"mappings":"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"}
|
package/dist/insights/index.d.ts
CHANGED
|
@@ -26,4 +26,8 @@ export * from "./drift.js";
|
|
|
26
26
|
export * from "./chronicle.js";
|
|
27
27
|
export * from "./oracle.js";
|
|
28
28
|
export * from "./constellation.js";
|
|
29
|
+
export * from "./cluster.js";
|
|
30
|
+
export * from "./network.js";
|
|
31
|
+
export * from "./manage.js";
|
|
32
|
+
export * from "./export-bundle.js";
|
|
29
33
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/insights/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/insights/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
|
package/dist/insights/index.js
CHANGED
|
@@ -26,4 +26,8 @@ export * from "./drift.js";
|
|
|
26
26
|
export * from "./chronicle.js";
|
|
27
27
|
export * from "./oracle.js";
|
|
28
28
|
export * from "./constellation.js";
|
|
29
|
+
export * from "./cluster.js";
|
|
30
|
+
export * from "./network.js";
|
|
31
|
+
export * from "./manage.js";
|
|
32
|
+
export * from "./export-bundle.js";
|
|
29
33
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/insights/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/insights/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mneme manage` — engineering management dashboard.
|
|
3
|
+
*
|
|
4
|
+
* The "King of Git Management" surface: rolls up multiple Mneme insights
|
|
5
|
+
* into a single CTO/EM-friendly view answering:
|
|
6
|
+
* - Team health: are we firefighting or shipping?
|
|
7
|
+
* - Bus factor: who is the keystone, what falls if they leave?
|
|
8
|
+
* - Skill matrix: who knows what, derived from commit history?
|
|
9
|
+
* - Knowledge succession: for each high-risk module, who's the
|
|
10
|
+
* understudy?
|
|
11
|
+
* - Trajectory: where is the team headed?
|
|
12
|
+
*
|
|
13
|
+
* No external services. Combines existing pure data extractors.
|
|
14
|
+
*/
|
|
15
|
+
import type { Commit } from "../types.js";
|
|
16
|
+
export interface SkillCell {
|
|
17
|
+
author: string;
|
|
18
|
+
area: string;
|
|
19
|
+
/** Touches in the area, normalized 0..1 against the area's busiest author. */
|
|
20
|
+
proficiency: number;
|
|
21
|
+
/** Days since this author last touched the area. */
|
|
22
|
+
daysSinceLastTouch: number;
|
|
23
|
+
}
|
|
24
|
+
export interface SuccessionPlan {
|
|
25
|
+
area: string;
|
|
26
|
+
primary: string;
|
|
27
|
+
understudy: string | null;
|
|
28
|
+
/** 0..1 — confidence that the understudy can take over. */
|
|
29
|
+
confidence: number;
|
|
30
|
+
/** Risk score 0..1: 1 = no understudy + primary is bus-factor; 0 = healthy. */
|
|
31
|
+
risk: number;
|
|
32
|
+
}
|
|
33
|
+
export interface TeamHealthSnapshot {
|
|
34
|
+
windowCommits: number;
|
|
35
|
+
/** Composite 0..1 — higher is healthier. Reflects feature ratio + low collision rate + low bus-factor risk. */
|
|
36
|
+
overall: number;
|
|
37
|
+
/** Most recent drift bucket label and dominant kind. */
|
|
38
|
+
trajectory: {
|
|
39
|
+
label: string;
|
|
40
|
+
dominant: string;
|
|
41
|
+
};
|
|
42
|
+
/** Active collisions predicted by Oracle. */
|
|
43
|
+
predictedCollisions: number;
|
|
44
|
+
/** Maximum bus-factor risk across modules. */
|
|
45
|
+
maxSuccessionRisk: number;
|
|
46
|
+
notes: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface ManageReport {
|
|
49
|
+
windowDays: number;
|
|
50
|
+
health: TeamHealthSnapshot;
|
|
51
|
+
/** Per-area × per-author proficiency cells. */
|
|
52
|
+
skillMatrix: SkillCell[];
|
|
53
|
+
/** Areas + their primary owner, understudy candidate, and risk. */
|
|
54
|
+
succession: SuccessionPlan[];
|
|
55
|
+
}
|
|
56
|
+
export declare function buildManage(commits: Commit[], opts?: {
|
|
57
|
+
nowMs?: number;
|
|
58
|
+
windowDays?: number;
|
|
59
|
+
}): ManageReport;
|
|
60
|
+
//# sourceMappingURL=manage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.d.ts","sourceRoot":"","sources":["../../src/insights/manage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI1C,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,+GAA+G;IAC/G,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,6CAA6C;IAC7C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8CAA8C;IAC9C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,+CAA+C;IAC/C,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,mEAAmE;IACnE,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CAChB,GACL,YAAY,CA6Gd"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { buildDrift } from "./drift.js";
|
|
2
|
+
import { buildOracle } from "./oracle.js";
|
|
3
|
+
export function buildManage(commits, opts = {}) {
|
|
4
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
5
|
+
const windowDays = opts.windowDays ?? 90;
|
|
6
|
+
const cutoff = nowMs - windowDays * 86_400_000;
|
|
7
|
+
const recent = commits.filter((c) => new Date(c.authorDate).getTime() >= cutoff);
|
|
8
|
+
const drift = buildDrift(recent, { granularity: "month" });
|
|
9
|
+
const oracle = buildOracle(commits, { nowMs, windowDays });
|
|
10
|
+
// Per-area touches (top-level dirs)
|
|
11
|
+
const areaAuthorTouches = new Map();
|
|
12
|
+
const areaAuthorLast = new Map();
|
|
13
|
+
for (const c of recent) {
|
|
14
|
+
const a = c.authorName || c.authorEmail;
|
|
15
|
+
const t = new Date(c.authorDate).getTime();
|
|
16
|
+
for (const f of c.files) {
|
|
17
|
+
const area = f.split("/").slice(0, 2).join("/") || "(root)";
|
|
18
|
+
let m = areaAuthorTouches.get(area);
|
|
19
|
+
if (!m) {
|
|
20
|
+
m = new Map();
|
|
21
|
+
areaAuthorTouches.set(area, m);
|
|
22
|
+
}
|
|
23
|
+
m.set(a, (m.get(a) ?? 0) + 1);
|
|
24
|
+
let lm = areaAuthorLast.get(area);
|
|
25
|
+
if (!lm) {
|
|
26
|
+
lm = new Map();
|
|
27
|
+
areaAuthorLast.set(area, lm);
|
|
28
|
+
}
|
|
29
|
+
const cur = lm.get(a) ?? 0;
|
|
30
|
+
if (t > cur)
|
|
31
|
+
lm.set(a, t);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Build skill matrix
|
|
35
|
+
const skillMatrix = [];
|
|
36
|
+
for (const [area, m] of areaAuthorTouches) {
|
|
37
|
+
const max = Math.max(...m.values());
|
|
38
|
+
if (max === 0)
|
|
39
|
+
continue;
|
|
40
|
+
for (const [author, n] of m) {
|
|
41
|
+
const last = areaAuthorLast.get(area)?.get(author) ?? 0;
|
|
42
|
+
skillMatrix.push({
|
|
43
|
+
author,
|
|
44
|
+
area,
|
|
45
|
+
proficiency: Number((n / max).toFixed(3)),
|
|
46
|
+
daysSinceLastTouch: last === 0 ? -1 : Math.round((nowMs - last) / 86_400_000),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
skillMatrix.sort((a, b) => b.proficiency - a.proficiency);
|
|
51
|
+
// Build succession plans (per area)
|
|
52
|
+
const succession = [];
|
|
53
|
+
for (const [area, m] of areaAuthorTouches) {
|
|
54
|
+
const ranked = [...m.entries()].sort((a, b) => b[1] - a[1]);
|
|
55
|
+
if (ranked.length === 0)
|
|
56
|
+
continue;
|
|
57
|
+
const primary = ranked[0][0];
|
|
58
|
+
const primaryShare = ranked[0][1] / ranked.reduce((s, [, n]) => s + n, 0);
|
|
59
|
+
const understudy = ranked[1]?.[0] ?? null;
|
|
60
|
+
const understudyShare = ranked[1] ? ranked[1][1] / ranked.reduce((s, [, n]) => s + n, 0) : 0;
|
|
61
|
+
const confidence = understudy ? Number(Math.min(1, understudyShare * 3).toFixed(3)) : 0;
|
|
62
|
+
// risk: high primary share + no/weak understudy
|
|
63
|
+
const risk = Number(Math.min(1, Math.max(0, primaryShare - 0.5) * 2 * (1 - confidence)).toFixed(3));
|
|
64
|
+
succession.push({ area, primary, understudy, confidence, risk });
|
|
65
|
+
}
|
|
66
|
+
succession.sort((a, b) => b.risk - a.risk);
|
|
67
|
+
// Compute team health
|
|
68
|
+
const lastBucket = drift.buckets[drift.buckets.length - 1];
|
|
69
|
+
const trajectory = lastBucket
|
|
70
|
+
? { label: lastBucket.label, dominant: lastBucket.dominant }
|
|
71
|
+
: { label: "n/a", dominant: "other" };
|
|
72
|
+
const featureRatio = lastBucket
|
|
73
|
+
? (lastBucket.byKind.feature ?? 0) / Math.max(1, lastBucket.total)
|
|
74
|
+
: 0;
|
|
75
|
+
const fireRatio = lastBucket
|
|
76
|
+
? (lastBucket.byKind.firefight ?? 0) / Math.max(1, lastBucket.total)
|
|
77
|
+
: 0;
|
|
78
|
+
const collisionScore = oracle.collisions.length === 0 ? 1 : Math.max(0, 1 - oracle.collisions.length / 10);
|
|
79
|
+
const successionScore = succession.length === 0 ? 1 : 1 - Math.max(...succession.map((s) => s.risk), 0);
|
|
80
|
+
const overall = Number(((0.4 * (featureRatio + (1 - fireRatio)) / 2) + 0.3 * collisionScore + 0.3 * successionScore).toFixed(3));
|
|
81
|
+
const notes = [];
|
|
82
|
+
if (fireRatio > 0.4)
|
|
83
|
+
notes.push(`Firefight ratio is ${pct(fireRatio)} — last month was reactive. Consider a feature freeze.`);
|
|
84
|
+
if (oracle.collisions.length > 3)
|
|
85
|
+
notes.push(`${oracle.collisions.length} predicted collisions in next window — schedule a sync.`);
|
|
86
|
+
const maxRisk = Math.max(0, ...succession.map((s) => s.risk));
|
|
87
|
+
if (maxRisk > 0.6) {
|
|
88
|
+
const top = succession[0];
|
|
89
|
+
notes.push(`Highest succession risk: ${top.area} (primary @${top.primary}, ${top.understudy ? "weak understudy" : "no understudy"}).`);
|
|
90
|
+
}
|
|
91
|
+
if (notes.length === 0)
|
|
92
|
+
notes.push("No major risks detected. Team trajectory looks healthy.");
|
|
93
|
+
return {
|
|
94
|
+
windowDays,
|
|
95
|
+
health: {
|
|
96
|
+
windowCommits: recent.length,
|
|
97
|
+
overall,
|
|
98
|
+
trajectory,
|
|
99
|
+
predictedCollisions: oracle.collisions.length,
|
|
100
|
+
maxSuccessionRisk: Number(maxRisk.toFixed(3)),
|
|
101
|
+
notes,
|
|
102
|
+
},
|
|
103
|
+
skillMatrix,
|
|
104
|
+
succession,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function pct(r) {
|
|
108
|
+
return `${Math.round(r * 100)}%`;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=manage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.js","sourceRoot":"","sources":["../../src/insights/manage.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA2C1C,MAAM,UAAU,WAAW,CACzB,OAAiB,EACjB,OAGI,EAAE;IAEN,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;IAEzC,MAAM,MAAM,GAAG,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;IAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAC3B,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,IAAI,MAAM,CAClD,CAAC;IAEF,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IAE3D,oCAAoC;IACpC,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAA+B,CAAC;IACjE,MAAM,cAAc,GAAG,IAAI,GAAG,EAA+B,CAAC;IAC9D,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,WAAW,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC;YAC5D,IAAI,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,CAAC,EAAE,CAAC;gBACP,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;gBACd,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACjC,CAAC;YACD,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9B,IAAI,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;gBACf,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/B,CAAC;YACD,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,GAAG,GAAG;gBAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,MAAM,WAAW,GAAgB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,iBAAiB,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACpC,IAAI,GAAG,KAAK,CAAC;YAAE,SAAS;QACxB,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxD,WAAW,CAAC,IAAI,CAAC;gBACf,MAAM;gBACN,IAAI;gBACJ,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACzC,kBAAkB,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC;aAC9E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;IAE1D,oCAAoC;IACpC,MAAM,UAAU,GAAqB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,iBAAiB,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAClC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3E,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC1C,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxF,gDAAgD;QAChD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACpG,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAE3C,sBAAsB;IACtB,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,UAAU;QAC3B,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE;QAC5D,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAExC,MAAM,YAAY,GAAG,UAAU;QAC7B,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC;QAClE,CAAC,CAAC,CAAC,CAAC;IACN,MAAM,SAAS,GAAG,UAAU;QAC1B,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC;QACpE,CAAC,CAAC,CAAC,CAAC;IAEN,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC3G,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACxG,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,cAAc,GAAG,GAAG,GAAG,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjI,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS,GAAG,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,sBAAsB,GAAG,CAAC,SAAS,CAAC,wDAAwD,CAAC,CAAC;IAC9H,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,yDAAyD,CAAC,CAAC;IACnI,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,4BAA4B,GAAI,CAAC,IAAI,cAAc,GAAI,CAAC,OAAO,KAAK,GAAI,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;IAC5I,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;IAE9F,OAAO;QACL,UAAU;QACV,MAAM,EAAE;YACN,aAAa,EAAE,MAAM,CAAC,MAAM;YAC5B,OAAO;YACP,UAAU;YACV,mBAAmB,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM;YAC7C,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC7C,KAAK;SACN;QACD,WAAW;QACX,UAAU;KACX,CAAC;AACJ,CAAC;AAED,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.test.d.ts","sourceRoot":"","sources":["../../src/insights/manage.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { buildManage } from "./manage.js";
|
|
3
|
+
const NOW = new Date("2026-05-05").getTime();
|
|
4
|
+
function mk(p) {
|
|
5
|
+
return {
|
|
6
|
+
hash: p.hash,
|
|
7
|
+
shortHash: p.hash.slice(0, 7),
|
|
8
|
+
authorName: p.author,
|
|
9
|
+
authorEmail: p.author.toLowerCase() + "@x.com",
|
|
10
|
+
authorDate: p.date,
|
|
11
|
+
committerDate: p.date,
|
|
12
|
+
subject: p.subject,
|
|
13
|
+
body: "",
|
|
14
|
+
files: p.files ?? [],
|
|
15
|
+
parents: [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
describe("buildManage", () => {
|
|
19
|
+
it("returns sane defaults for empty input", () => {
|
|
20
|
+
const r = buildManage([], { nowMs: NOW });
|
|
21
|
+
expect(r.health.windowCommits).toBe(0);
|
|
22
|
+
expect(r.skillMatrix).toHaveLength(0);
|
|
23
|
+
expect(r.succession).toHaveLength(0);
|
|
24
|
+
expect(r.health.notes.length).toBeGreaterThan(0);
|
|
25
|
+
});
|
|
26
|
+
it("fills skill matrix with per-area proficiency", () => {
|
|
27
|
+
const commits = [
|
|
28
|
+
mk({ hash: "a1", date: "2026-04-01", subject: "x", author: "Alice", files: ["src/auth/x.ts"] }),
|
|
29
|
+
mk({ hash: "a2", date: "2026-04-02", subject: "x", author: "Alice", files: ["src/auth/y.ts"] }),
|
|
30
|
+
mk({ hash: "b1", date: "2026-04-03", subject: "x", author: "Bob", files: ["src/payments/z.ts"] }),
|
|
31
|
+
];
|
|
32
|
+
const r = buildManage(commits, { nowMs: NOW });
|
|
33
|
+
const aliceAuth = r.skillMatrix.find((c) => c.author === "Alice" && c.area === "src/auth");
|
|
34
|
+
expect(aliceAuth).toBeDefined();
|
|
35
|
+
expect(aliceAuth.proficiency).toBe(1);
|
|
36
|
+
});
|
|
37
|
+
it("succession surfaces high-risk areas where one author dominates and no understudy", () => {
|
|
38
|
+
const commits = Array.from({ length: 12 }, (_, i) => mk({
|
|
39
|
+
hash: `a${i}`,
|
|
40
|
+
date: `2026-04-${(i + 1).toString().padStart(2, "0")}`,
|
|
41
|
+
subject: "x",
|
|
42
|
+
author: "Alice",
|
|
43
|
+
files: ["src/legacy/x.ts"],
|
|
44
|
+
}));
|
|
45
|
+
const r = buildManage(commits, { nowMs: NOW });
|
|
46
|
+
const legacy = r.succession.find((s) => s.area === "src/legacy");
|
|
47
|
+
expect(legacy).toBeDefined();
|
|
48
|
+
expect(legacy.understudy).toBeNull();
|
|
49
|
+
expect(legacy.risk).toBeGreaterThan(0.5);
|
|
50
|
+
});
|
|
51
|
+
it("succession risk is low when an understudy contributes meaningfully", () => {
|
|
52
|
+
const commits = [
|
|
53
|
+
...Array.from({ length: 8 }, (_, i) => mk({ hash: `a${i}`, date: `2026-04-${(i + 1).toString().padStart(2, "0")}`, subject: "x", author: "Alice", files: ["src/auth/x.ts"] })),
|
|
54
|
+
...Array.from({ length: 6 }, (_, i) => mk({ hash: `b${i}`, date: `2026-04-${(i + 1).toString().padStart(2, "0")}`, subject: "x", author: "Bob", files: ["src/auth/x.ts"] })),
|
|
55
|
+
];
|
|
56
|
+
const r = buildManage(commits, { nowMs: NOW });
|
|
57
|
+
const auth = r.succession.find((s) => s.area === "src/auth");
|
|
58
|
+
expect(auth).toBeDefined();
|
|
59
|
+
expect(auth.understudy).toBe("Bob");
|
|
60
|
+
expect(auth.risk).toBeLessThan(0.5);
|
|
61
|
+
});
|
|
62
|
+
it("health.overall is bounded 0..1", () => {
|
|
63
|
+
const commits = Array.from({ length: 5 }, (_, i) => mk({ hash: `a${i}`, date: `2026-04-0${i + 1}`, subject: `feat: ${i}`, author: "Alice", files: ["x.ts"] }));
|
|
64
|
+
const r = buildManage(commits, { nowMs: NOW });
|
|
65
|
+
expect(r.health.overall).toBeGreaterThanOrEqual(0);
|
|
66
|
+
expect(r.health.overall).toBeLessThanOrEqual(1);
|
|
67
|
+
});
|
|
68
|
+
it("trajectory reflects last drift bucket", () => {
|
|
69
|
+
const commits = [
|
|
70
|
+
mk({ hash: "a1", date: "2026-04-01", subject: "feat: x", author: "Alice", files: ["x.ts"] }),
|
|
71
|
+
mk({ hash: "a2", date: "2026-04-02", subject: "feat: y", author: "Alice", files: ["x.ts"] }),
|
|
72
|
+
];
|
|
73
|
+
const r = buildManage(commits, { nowMs: NOW });
|
|
74
|
+
expect(r.health.trajectory.label).not.toBe("n/a");
|
|
75
|
+
});
|
|
76
|
+
it("notes mention firefight when fire ratio is high", () => {
|
|
77
|
+
const commits = Array.from({ length: 8 }, (_, i) => mk({ hash: `b${i}`, date: `2026-04-${(i + 1).toString().padStart(2, "0")}`, subject: "fix critical bug", author: "Alice", files: ["x.ts"] }));
|
|
78
|
+
const r = buildManage(commits, { nowMs: NOW });
|
|
79
|
+
const fireNote = r.health.notes.find((n) => n.toLowerCase().includes("firefight"));
|
|
80
|
+
expect(fireNote).toBeDefined();
|
|
81
|
+
});
|
|
82
|
+
it("succession sorted by risk descending", () => {
|
|
83
|
+
const commits = [
|
|
84
|
+
...Array.from({ length: 10 }, (_, i) => mk({ hash: `a${i}`, date: `2026-04-${(i + 1).toString().padStart(2, "0")}`, subject: "x", author: "Alice", files: ["src/risky/x.ts"] })),
|
|
85
|
+
...Array.from({ length: 5 }, (_, i) => mk({ hash: `b${i}`, date: `2026-04-${(i + 1).toString().padStart(2, "0")}`, subject: "x", author: "Bob", files: ["src/safe/y.ts"] })),
|
|
86
|
+
...Array.from({ length: 4 }, (_, i) => mk({ hash: `c${i}`, date: `2026-04-${(i + 1).toString().padStart(2, "0")}`, subject: "x", author: "Carol", files: ["src/safe/y.ts"] })),
|
|
87
|
+
];
|
|
88
|
+
const r = buildManage(commits, { nowMs: NOW });
|
|
89
|
+
for (let i = 1; i < r.succession.length; i++) {
|
|
90
|
+
expect(r.succession[i - 1].risk).toBeGreaterThanOrEqual(r.succession[i].risk);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=manage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.test.js","sourceRoot":"","sources":["../../src/insights/manage.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mneme network` — author social graph with semantic edges.
|
|
3
|
+
*
|
|
4
|
+
* Closes the "author network with semantic edges" gap from the
|
|
5
|
+
* landscape survey: Unblocked.com is the closest commercial competitor
|
|
6
|
+
* (closed-source, PR-only, paid). No open-source tool builds an author
|
|
7
|
+
* social graph weighted by *what they collaborated on*, not just
|
|
8
|
+
* how often.
|
|
9
|
+
*
|
|
10
|
+
* Edges between authors are weighted by:
|
|
11
|
+
* - co-edits : how often they touched the same file
|
|
12
|
+
* - co-time : how often they committed within the same window
|
|
13
|
+
* - co-topic : how often their commit messages share vocabulary
|
|
14
|
+
*
|
|
15
|
+
* The semantic component (co-topic) is what makes this novel — it
|
|
16
|
+
* surfaces "Alice and Bob both worked on the auth refactor" even when
|
|
17
|
+
* they touched different files.
|
|
18
|
+
*
|
|
19
|
+
* Pure data extraction. CLI renders.
|
|
20
|
+
*/
|
|
21
|
+
import type { Commit } from "../types.js";
|
|
22
|
+
export interface AuthorNode {
|
|
23
|
+
author: string;
|
|
24
|
+
/** Total commits in window. */
|
|
25
|
+
commits: number;
|
|
26
|
+
/** Number of distinct other authors collaborated with. */
|
|
27
|
+
collaborators: number;
|
|
28
|
+
/** Centrality 0..1 — how "bridging" they are between others. */
|
|
29
|
+
centrality: number;
|
|
30
|
+
}
|
|
31
|
+
export interface AuthorEdge {
|
|
32
|
+
authorA: string;
|
|
33
|
+
authorB: string;
|
|
34
|
+
/** Weight 0..1 — composite of co-edit, co-time, co-topic. */
|
|
35
|
+
weight: number;
|
|
36
|
+
/** Per-axis breakdown. */
|
|
37
|
+
axes: {
|
|
38
|
+
coEdit: number;
|
|
39
|
+
coTime: number;
|
|
40
|
+
coTopic: number;
|
|
41
|
+
};
|
|
42
|
+
/** Top shared vocabulary terms (drives the "what they worked on together" semantic edge label). */
|
|
43
|
+
sharedTerms: string[];
|
|
44
|
+
}
|
|
45
|
+
export interface NetworkReport {
|
|
46
|
+
windowCommits: number;
|
|
47
|
+
nodes: AuthorNode[];
|
|
48
|
+
edges: AuthorEdge[];
|
|
49
|
+
/** Detected silos — sets of authors with weak edges to others. */
|
|
50
|
+
silos: string[][];
|
|
51
|
+
/** Detected bridges — authors connecting otherwise weakly-linked groups. */
|
|
52
|
+
bridges: string[];
|
|
53
|
+
}
|
|
54
|
+
export declare function buildNetwork(commits: Commit[], opts?: {
|
|
55
|
+
coTimeWindowDays?: number;
|
|
56
|
+
minEdgeWeight?: number;
|
|
57
|
+
minAuthorCommits?: number;
|
|
58
|
+
}): NetworkReport;
|
|
59
|
+
//# sourceMappingURL=network.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/insights/network.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,mGAAmG;IACnG,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,kEAAkE;IAClE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IAClB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AASD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE;IACJ,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACtB,GACL,aAAa,CA+Gf"}
|