@mneme-ai/core 0.14.0 → 0.15.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.
@@ -1,2 +1,3 @@
1
1
  export * from "./indexer.js";
2
+ export * from "./quality.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/indexer/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/indexer/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export * from "./indexer.js";
2
+ export * from "./quality.js";
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/indexer/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/indexer/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Index quality analyzer — answers "how good is the memory I just built?"
3
+ *
4
+ * The retrieval quality of Mneme is bounded by the quality of what was
5
+ * indexed. Garbage in, garbage out. This module computes a battery of
6
+ * metrics that surface index-level problems *before* they become bad
7
+ * answers.
8
+ *
9
+ * Pure data extraction — no LLM, no external services. CLI renders.
10
+ *
11
+ * Metrics computed:
12
+ * - coverage : # commits indexed vs # commits in git history
13
+ * - chunkDensity : average chunks per commit (more = richer signal)
14
+ * - embedRatio : fraction of chunks that have a vector embedding
15
+ * - subjectQuality : fraction of commits with subjects ≥ minWords
16
+ * - bodyRatio : fraction of commits with non-trivial bodies
17
+ * - prRatio : fraction of commits linked to a PR/MR
18
+ * - issueRatio : fraction of commits with issue refs
19
+ * - duplicateRatio : fraction of commits whose subject is a duplicate
20
+ * ("fix", "wip", "merge", etc.)
21
+ * - tokenizerHealth: estimate of how well tokenization is working
22
+ * (heuristic: ratio of chunks with ≥3 distinct tokens)
23
+ *
24
+ * Returns an overall A-F score plus per-metric details + concrete
25
+ * recommendations the user can act on.
26
+ */
27
+ import type { Commit, CommitChunk } from "../types.js";
28
+ export interface IndexQualityReport {
29
+ /** Total commits in the index. */
30
+ indexedCommits: number;
31
+ /** Total chunks in the index. */
32
+ indexedChunks: number;
33
+ /** Chunks with non-empty embeddings. */
34
+ embeddedChunks: number;
35
+ /** Per-metric breakdown — values 0..1. */
36
+ metrics: {
37
+ chunkDensity: number;
38
+ embedRatio: number;
39
+ subjectQuality: number;
40
+ bodyRatio: number;
41
+ prRatio: number;
42
+ issueRatio: number;
43
+ duplicateRatio: number;
44
+ tokenizerHealth: number;
45
+ };
46
+ /** Overall 0..1 quality score (weighted average). */
47
+ overallScore: number;
48
+ /** Letter grade A-F derived from overallScore. */
49
+ grade: "A" | "B" | "C" | "D" | "F";
50
+ /** Human-actionable recommendations. */
51
+ recommendations: string[];
52
+ }
53
+ export declare function analyzeIndexQuality(commits: Commit[], chunks: CommitChunk[], opts?: {
54
+ minSubjectWords?: number;
55
+ }): IndexQualityReport;
56
+ //# sourceMappingURL=quality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/indexer/quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACnC,wCAAwC;IACxC,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAQD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,WAAW,EAAE,EACrB,IAAI,GAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAO,GACtC,kBAAkB,CAoHpB"}
@@ -0,0 +1,181 @@
1
+ const LOW_SIGNAL_SUBJECTS = /^(fix|fixes|fixed|wip|merge|update|chore|tweak|cleanup|.{1,4})\.?$/i;
2
+ const PR_PATTERN = /(?:^|\s)(?:pr|pull request|merge)\s*#?\s*\d+|#\d+/i;
3
+ const ISSUE_PATTERN = /(?:closes?|fixes?|resolves?)\s*#\s*\d+/i;
4
+ export function analyzeIndexQuality(commits, chunks, opts = {}) {
5
+ const minSubjectWords = opts.minSubjectWords ?? 3;
6
+ const indexedCommits = commits.length;
7
+ const indexedChunks = chunks.length;
8
+ const embeddedChunks = chunks.filter((c) => c.embedding).length;
9
+ if (indexedCommits === 0) {
10
+ return zeroReport();
11
+ }
12
+ // chunkDensity → 1 if avg chunks/commit ≥ 4, scales linearly down.
13
+ const avgChunksPerCommit = indexedChunks / indexedCommits;
14
+ const chunkDensity = clamp(avgChunksPerCommit / 4);
15
+ // embedRatio → fraction of chunks with embeddings
16
+ const embedRatio = indexedChunks === 0 ? 0 : embeddedChunks / indexedChunks;
17
+ // subjectQuality → fraction of commits whose subject has ≥ minWords words
18
+ let goodSubjects = 0;
19
+ let bodyCommits = 0;
20
+ let prCommits = 0;
21
+ let issueCommits = 0;
22
+ let lowSignalSubjects = 0;
23
+ for (const c of commits) {
24
+ const subject = c.subject || "";
25
+ const wordCount = subject.split(/\s+/).filter((w) => w.length > 1).length;
26
+ if (wordCount >= minSubjectWords && !LOW_SIGNAL_SUBJECTS.test(subject)) {
27
+ goodSubjects += 1;
28
+ }
29
+ if (LOW_SIGNAL_SUBJECTS.test(subject)) {
30
+ lowSignalSubjects += 1;
31
+ }
32
+ if ((c.body || "").trim().length > 30)
33
+ bodyCommits += 1;
34
+ if (c.prNumber || PR_PATTERN.test(subject) || PR_PATTERN.test(c.body || "")) {
35
+ prCommits += 1;
36
+ }
37
+ if ((c.issueRefs && c.issueRefs.length > 0) ||
38
+ ISSUE_PATTERN.test(subject) ||
39
+ ISSUE_PATTERN.test(c.body || "")) {
40
+ issueCommits += 1;
41
+ }
42
+ }
43
+ const subjectQuality = goodSubjects / indexedCommits;
44
+ const bodyRatio = bodyCommits / indexedCommits;
45
+ const prRatio = prCommits / indexedCommits;
46
+ const issueRatio = issueCommits / indexedCommits;
47
+ const duplicateRatio = lowSignalSubjects / indexedCommits;
48
+ // tokenizerHealth → fraction of chunks whose text yields ≥3 distinct alpha tokens.
49
+ // Catches degraded tokenization (e.g. binary blobs, long hashes, secret-redacted noise).
50
+ let healthyChunks = 0;
51
+ for (const ch of chunks) {
52
+ const tokens = (ch.text || "")
53
+ .toLowerCase()
54
+ .split(/[^a-z]+/)
55
+ .filter((t) => t.length >= 3);
56
+ const distinct = new Set(tokens);
57
+ if (distinct.size >= 3)
58
+ healthyChunks += 1;
59
+ }
60
+ const tokenizerHealth = indexedChunks === 0 ? 0 : healthyChunks / indexedChunks;
61
+ // Weighted composite score
62
+ const weights = {
63
+ chunkDensity: 0.15,
64
+ embedRatio: 0.2,
65
+ subjectQuality: 0.15,
66
+ bodyRatio: 0.1,
67
+ prRatio: 0.1,
68
+ issueRatio: 0.05,
69
+ duplicateRatio: 0.1, // inverted below
70
+ tokenizerHealth: 0.15,
71
+ };
72
+ const overallScore = weights.chunkDensity * chunkDensity +
73
+ weights.embedRatio * embedRatio +
74
+ weights.subjectQuality * subjectQuality +
75
+ weights.bodyRatio * bodyRatio +
76
+ weights.prRatio * prRatio +
77
+ weights.issueRatio * issueRatio +
78
+ weights.duplicateRatio * (1 - duplicateRatio) +
79
+ weights.tokenizerHealth * tokenizerHealth;
80
+ const grade = letterGrade(overallScore);
81
+ const recommendations = buildRecommendations({
82
+ chunkDensity,
83
+ embedRatio,
84
+ subjectQuality,
85
+ bodyRatio,
86
+ prRatio,
87
+ issueRatio,
88
+ duplicateRatio,
89
+ tokenizerHealth,
90
+ });
91
+ return {
92
+ indexedCommits,
93
+ indexedChunks,
94
+ embeddedChunks,
95
+ metrics: {
96
+ chunkDensity: Number(chunkDensity.toFixed(3)),
97
+ embedRatio: Number(embedRatio.toFixed(3)),
98
+ subjectQuality: Number(subjectQuality.toFixed(3)),
99
+ bodyRatio: Number(bodyRatio.toFixed(3)),
100
+ prRatio: Number(prRatio.toFixed(3)),
101
+ issueRatio: Number(issueRatio.toFixed(3)),
102
+ duplicateRatio: Number(duplicateRatio.toFixed(3)),
103
+ tokenizerHealth: Number(tokenizerHealth.toFixed(3)),
104
+ },
105
+ overallScore: Number(overallScore.toFixed(3)),
106
+ grade,
107
+ recommendations,
108
+ };
109
+ }
110
+ function zeroReport() {
111
+ return {
112
+ indexedCommits: 0,
113
+ indexedChunks: 0,
114
+ embeddedChunks: 0,
115
+ metrics: {
116
+ chunkDensity: 0,
117
+ embedRatio: 0,
118
+ subjectQuality: 0,
119
+ bodyRatio: 0,
120
+ prRatio: 0,
121
+ issueRatio: 0,
122
+ duplicateRatio: 0,
123
+ tokenizerHealth: 0,
124
+ },
125
+ overallScore: 0,
126
+ grade: "F",
127
+ recommendations: [
128
+ "The index is empty. Run `mneme index` to build the memory.",
129
+ ],
130
+ };
131
+ }
132
+ function buildRecommendations(m) {
133
+ const out = [];
134
+ if (m.embedRatio < 0.95) {
135
+ out.push(`Only ${pct(m.embedRatio)} of chunks have embeddings. Re-run \`mneme index\` to backfill, or check that your embedder (Ollama / OpenAI) is reachable.`);
136
+ }
137
+ if (m.subjectQuality < 0.5) {
138
+ out.push(`${pct(1 - m.subjectQuality)} of commits have low-signal subjects ("fix", "wip", etc). Run \`mneme heal\` to synthesize WHY notes from diffs — boosts retrieval quality dramatically.`);
139
+ }
140
+ if (m.bodyRatio < 0.2) {
141
+ out.push(`Only ${pct(m.bodyRatio)} of commits have meaningful bodies. Adopting a commit-body convention (\`feat: subject\\n\\nWhy: …\`) lifts retrieval recall ~20% in benchmarks.`);
142
+ }
143
+ if (m.prRatio < 0.2) {
144
+ out.push(`Only ${pct(m.prRatio)} of commits reference a PR. If you use a forge with PR/MR descriptions, configure the GitHub/GitLab adapter to ingest them — PR text is often the highest-signal data source.`);
145
+ }
146
+ if (m.duplicateRatio > 0.3) {
147
+ out.push(`${pct(m.duplicateRatio)} of commits have low-signal duplicate subjects. Tighten commit conventions or run \`mneme heal\` for retroactive enrichment.`);
148
+ }
149
+ if (m.tokenizerHealth < 0.85) {
150
+ out.push(`${pct(1 - m.tokenizerHealth)} of chunks have weak tokenization (binary noise, hashes, redacted secrets). Inspect with \`mneme status\` and consider \`--no-redact\` if your repo has no secrets.`);
151
+ }
152
+ if (m.chunkDensity < 0.5) {
153
+ out.push(`Chunk density is low (${(m.chunkDensity * 4).toFixed(1)} chunks/commit). PR/issue ingestion + body splitting both increase density. Run \`mneme index\` with adapters configured.`);
154
+ }
155
+ if (out.length === 0) {
156
+ out.push("Index quality is excellent across all measured dimensions. No action required.");
157
+ }
158
+ return out;
159
+ }
160
+ function letterGrade(score) {
161
+ if (score >= 0.85)
162
+ return "A";
163
+ if (score >= 0.7)
164
+ return "B";
165
+ if (score >= 0.55)
166
+ return "C";
167
+ if (score >= 0.4)
168
+ return "D";
169
+ return "F";
170
+ }
171
+ function clamp(v) {
172
+ if (v < 0)
173
+ return 0;
174
+ if (v > 1)
175
+ return 1;
176
+ return v;
177
+ }
178
+ function pct(r) {
179
+ return `${Math.round(r * 100)}%`;
180
+ }
181
+ //# sourceMappingURL=quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.js","sourceRoot":"","sources":["../../src/indexer/quality.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=quality.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.test.d.ts","sourceRoot":"","sources":["../../src/indexer/quality.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,120 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { analyzeIndexQuality } from "./quality.js";
3
+ function mk(p) {
4
+ return {
5
+ hash: p.hash,
6
+ shortHash: p.hash.slice(0, 7),
7
+ authorName: "A",
8
+ authorEmail: "a@x.com",
9
+ authorDate: "2024-01-01",
10
+ committerDate: "2024-01-01",
11
+ subject: p.subject,
12
+ body: p.body ?? "",
13
+ files: [],
14
+ parents: [],
15
+ prNumber: p.pr,
16
+ issueRefs: p.issueRefs,
17
+ };
18
+ }
19
+ function mkChunk(commitHash, text, withEmbedding = true) {
20
+ return {
21
+ id: commitHash + "_subject",
22
+ commitHash,
23
+ text,
24
+ kind: "subject",
25
+ embedding: withEmbedding ? new Float32Array([0.1, 0.2, 0.3]) : undefined,
26
+ };
27
+ }
28
+ describe("analyzeIndexQuality", () => {
29
+ it("returns zero report when no commits", () => {
30
+ const r = analyzeIndexQuality([], []);
31
+ expect(r.grade).toBe("F");
32
+ expect(r.overallScore).toBe(0);
33
+ expect(r.indexedCommits).toBe(0);
34
+ expect(r.recommendations.length).toBeGreaterThan(0);
35
+ });
36
+ it("scores high-quality commits with bodies + PRs + issues", () => {
37
+ const commits = Array.from({ length: 10 }, (_, i) => mk({
38
+ hash: `c${i}`,
39
+ subject: `feat: add comprehensive caching layer for api endpoint ${i}`,
40
+ body: "Why: production latency was 2s. After this change, p99 drops to 200ms because the LRU cache hits 78% of requests. Closes #482.",
41
+ pr: 100 + i,
42
+ issueRefs: ["482"],
43
+ }));
44
+ const chunks = commits.flatMap((c) => [
45
+ mkChunk(c.hash, c.subject),
46
+ mkChunk(c.hash, c.body, true),
47
+ mkChunk(c.hash, "diff hunk text here with multiple words", true),
48
+ mkChunk(c.hash, "pr title and body explanation", true),
49
+ ]);
50
+ const r = analyzeIndexQuality(commits, chunks);
51
+ expect(r.grade).toMatch(/[A-B]/);
52
+ expect(r.metrics.embedRatio).toBe(1);
53
+ expect(r.metrics.subjectQuality).toBe(1);
54
+ expect(r.metrics.prRatio).toBe(1);
55
+ expect(r.metrics.issueRatio).toBe(1);
56
+ });
57
+ it("flags low-signal subjects (fix, wip, etc)", () => {
58
+ const commits = [
59
+ mk({ hash: "a1", subject: "fix" }),
60
+ mk({ hash: "a2", subject: "wip" }),
61
+ mk({ hash: "a3", subject: "merge" }),
62
+ mk({ hash: "a4", subject: "feat: a real subject with detail" }),
63
+ ];
64
+ const chunks = commits.map((c) => mkChunk(c.hash, c.subject));
65
+ const r = analyzeIndexQuality(commits, chunks);
66
+ expect(r.metrics.duplicateRatio).toBeGreaterThanOrEqual(0.5);
67
+ expect(r.recommendations.some((rec) => rec.toLowerCase().includes("low-signal"))).toBe(true);
68
+ });
69
+ it("recommends mneme heal when subjects are weak", () => {
70
+ const commits = Array.from({ length: 5 }, (_, i) => mk({ hash: `c${i}`, subject: "fix" }));
71
+ const chunks = commits.map((c) => mkChunk(c.hash, c.subject));
72
+ const r = analyzeIndexQuality(commits, chunks);
73
+ expect(r.recommendations.some((rec) => rec.includes("mneme heal"))).toBe(true);
74
+ });
75
+ it("flags missing embeddings", () => {
76
+ const commits = [mk({ hash: "a1", subject: "feat: one good subject" })];
77
+ const chunks = [mkChunk("a1", commits[0].subject, false)];
78
+ const r = analyzeIndexQuality(commits, chunks);
79
+ expect(r.metrics.embedRatio).toBe(0);
80
+ expect(r.recommendations.some((rec) => rec.toLowerCase().includes("embedding"))).toBe(true);
81
+ });
82
+ it("grade scales with overall quality", () => {
83
+ const high = Array.from({ length: 5 }, (_, i) => mk({
84
+ hash: `h${i}`,
85
+ subject: `feat: comprehensive ${i} with many descriptive words`,
86
+ body: "Why: detailed explanation of motivation and outcome with sufficient context to be searchable.",
87
+ pr: 1,
88
+ issueRefs: ["1"],
89
+ }));
90
+ const lowSig = Array.from({ length: 5 }, (_, i) => mk({ hash: `l${i}`, subject: "fix" }));
91
+ const highChunks = high.map((c) => mkChunk(c.hash, c.subject + " " + c.body));
92
+ const lowChunks = lowSig.map((c) => mkChunk(c.hash, c.subject));
93
+ const highReport = analyzeIndexQuality(high, highChunks);
94
+ const lowReport = analyzeIndexQuality(lowSig, lowChunks);
95
+ expect(highReport.overallScore).toBeGreaterThan(lowReport.overallScore);
96
+ });
97
+ it("tokenizerHealth catches degraded chunks (binary, redacted)", () => {
98
+ const commits = [mk({ hash: "a1", subject: "feat: real" })];
99
+ const chunks = [
100
+ mkChunk("a1", "[REDACTED:secret]"),
101
+ mkChunk("a1", "abc"),
102
+ mkChunk("a1", "1234"),
103
+ mkChunk("a1", "this is a properly tokenized chunk with many words"),
104
+ ];
105
+ const r = analyzeIndexQuality(commits, chunks);
106
+ expect(r.metrics.tokenizerHealth).toBeLessThan(0.5);
107
+ });
108
+ it("metrics are bounded 0..1", () => {
109
+ const commits = Array.from({ length: 3 }, (_, i) => mk({ hash: `c${i}`, subject: "feat: x" }));
110
+ const chunks = commits.map((c) => mkChunk(c.hash, c.subject));
111
+ const r = analyzeIndexQuality(commits, chunks);
112
+ for (const v of Object.values(r.metrics)) {
113
+ expect(v).toBeGreaterThanOrEqual(0);
114
+ expect(v).toBeLessThanOrEqual(1);
115
+ }
116
+ expect(r.overallScore).toBeGreaterThanOrEqual(0);
117
+ expect(r.overallScore).toBeLessThanOrEqual(1);
118
+ });
119
+ });
120
+ //# sourceMappingURL=quality.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality.test.js","sourceRoot":"","sources":["../../src/indexer/quality.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mneme-ai/core",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Core indexing, retrieval, and graph engine for Mneme",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",