@mneme-ai/core 2.24.0 → 2.25.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.
Files changed (37) hide show
  1. package/dist/codegraph/builder.d.ts +27 -0
  2. package/dist/codegraph/builder.d.ts.map +1 -0
  3. package/dist/codegraph/builder.js +309 -0
  4. package/dist/codegraph/builder.js.map +1 -0
  5. package/dist/codegraph/codegraph.test.d.ts +2 -0
  6. package/dist/codegraph/codegraph.test.d.ts.map +1 -0
  7. package/dist/codegraph/codegraph.test.js +179 -0
  8. package/dist/codegraph/codegraph.test.js.map +1 -0
  9. package/dist/codegraph/drift.d.ts +27 -0
  10. package/dist/codegraph/drift.d.ts.map +1 -0
  11. package/dist/codegraph/drift.js +126 -0
  12. package/dist/codegraph/drift.js.map +1 -0
  13. package/dist/codegraph/index.d.ts +10 -0
  14. package/dist/codegraph/index.d.ts.map +1 -0
  15. package/dist/codegraph/index.js +10 -0
  16. package/dist/codegraph/index.js.map +1 -0
  17. package/dist/codegraph/merkle.d.ts +40 -0
  18. package/dist/codegraph/merkle.d.ts.map +1 -0
  19. package/dist/codegraph/merkle.js +68 -0
  20. package/dist/codegraph/merkle.js.map +1 -0
  21. package/dist/codegraph/query.d.ts +14 -0
  22. package/dist/codegraph/query.d.ts.map +1 -0
  23. package/dist/codegraph/query.js +56 -0
  24. package/dist/codegraph/query.js.map +1 -0
  25. package/dist/codegraph/store.d.ts +37 -0
  26. package/dist/codegraph/store.d.ts.map +1 -0
  27. package/dist/codegraph/store.js +133 -0
  28. package/dist/codegraph/store.js.map +1 -0
  29. package/dist/codegraph/types.d.ts +140 -0
  30. package/dist/codegraph/types.d.ts.map +1 -0
  31. package/dist/codegraph/types.js +39 -0
  32. package/dist/codegraph/types.js.map +1 -0
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +9 -0
  36. package/dist/index.js.map +1 -1
  37. package/package.json +1 -1
@@ -0,0 +1,126 @@
1
+ /**
2
+ * v2.25.0 — Drift sentinel for LIVING SOUL codegraph.
3
+ *
4
+ * Compares the persisted snapshot against the current working tree and
5
+ * emits one DriftEvent per broken edge:
6
+ * - file deleted (src or dst missing)
7
+ * - file renamed (symbol moved to another path)
8
+ * - edge stale (file mtime > builtAt by > N hours)
9
+ *
10
+ * Pure-IO; no daemon required. The daemon can call this on every tick
11
+ * + fan-out severity ≥ "high" events to the notifier so the user gets
12
+ * a heads-up before the AI starts editing the wrong file.
13
+ */
14
+ import { existsSync, statSync } from "node:fs";
15
+ import { resolve } from "node:path";
16
+ import { recordDrift } from "./store.js";
17
+ const STALE_HOURS = 24;
18
+ /** Scan the graph against the current working tree. */
19
+ export function detectDrift(graph, opts = {}) {
20
+ const events = [];
21
+ const now = Date.now();
22
+ const builtAtMs = Date.parse(graph.builtAt);
23
+ const staleThreshold = STALE_HOURS * 3600 * 1000;
24
+ // Cache file existence + mtime
25
+ const fileMeta = new Map();
26
+ function fileOf(path) {
27
+ let m = fileMeta.get(path);
28
+ if (m)
29
+ return m;
30
+ const abs = resolve(graph.repoRoot, path);
31
+ if (!existsSync(abs)) {
32
+ m = { exists: false, mtime: 0 };
33
+ }
34
+ else {
35
+ try {
36
+ const st = statSync(abs);
37
+ m = { exists: true, mtime: st.mtimeMs };
38
+ }
39
+ catch {
40
+ m = { exists: false, mtime: 0 };
41
+ }
42
+ }
43
+ fileMeta.set(path, m);
44
+ return m;
45
+ }
46
+ let brokenEdges = 0;
47
+ let staleEdges = 0;
48
+ let missingFiles = 0;
49
+ const missingPathSet = new Set();
50
+ for (const edge of graph.edges.values()) {
51
+ const src = graph.nodes.get(edge.src);
52
+ const dst = graph.nodes.get(edge.dst);
53
+ if (!src || !dst)
54
+ continue;
55
+ // Skip edges to external deps; we can't trivially check existence.
56
+ if (dst.kind !== "external") {
57
+ const dstMeta = fileOf(dst.path);
58
+ if (!dstMeta.exists) {
59
+ brokenEdges++;
60
+ if (!missingPathSet.has(dst.path)) {
61
+ missingFiles++;
62
+ missingPathSet.add(dst.path);
63
+ }
64
+ const ev = {
65
+ at: new Date().toISOString(),
66
+ edgeId: edge.id,
67
+ kind: edge.kind === "imports" ? "dst-missing" : "file-deleted",
68
+ reason: `dst file ${dst.path} no longer exists (edge.kind=${edge.kind})`,
69
+ severity: edge.kind === "imports" ? "high" : "medium",
70
+ };
71
+ events.push(ev);
72
+ continue;
73
+ }
74
+ }
75
+ const srcMeta = fileOf(src.path);
76
+ if (!srcMeta.exists) {
77
+ brokenEdges++;
78
+ if (!missingPathSet.has(src.path)) {
79
+ missingFiles++;
80
+ missingPathSet.add(src.path);
81
+ }
82
+ events.push({
83
+ at: new Date().toISOString(),
84
+ edgeId: edge.id,
85
+ kind: "src-missing",
86
+ reason: `src file ${src.path} no longer exists`,
87
+ severity: "high",
88
+ });
89
+ continue;
90
+ }
91
+ // Edge-stale check (only flag if mtime > builtAt by > 24h)
92
+ if (now - builtAtMs > staleThreshold && srcMeta.mtime > builtAtMs + staleThreshold) {
93
+ staleEdges++;
94
+ events.push({
95
+ at: new Date().toISOString(),
96
+ edgeId: edge.id,
97
+ kind: "edge-stale",
98
+ reason: `src file ${src.path} changed > ${STALE_HOURS}h after graph was built`,
99
+ severity: "low",
100
+ });
101
+ }
102
+ }
103
+ if (opts.record) {
104
+ for (const ev of events)
105
+ recordDrift(graph.repoRoot, ev);
106
+ }
107
+ return { events, brokenEdges, staleEdges, missingFiles };
108
+ }
109
+ /** Filter edges that would BREAK if a file is renamed/deleted. */
110
+ export function edgesTouchedBy(graph, paths) {
111
+ const pathSet = new Set(paths.map((p) => p.replace(/\\/g, "/")));
112
+ const out = [];
113
+ for (const e of graph.edges.values()) {
114
+ const s = graph.nodes.get(e.src);
115
+ const d = graph.nodes.get(e.dst);
116
+ if (s && pathSet.has(s.path)) {
117
+ out.push(e);
118
+ continue;
119
+ }
120
+ if (d && pathSet.has(d.path)) {
121
+ out.push(e);
122
+ }
123
+ }
124
+ return out;
125
+ }
126
+ //# sourceMappingURL=drift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/codegraph/drift.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,WAAW,GAAG,EAAE,CAAC;AASvB,uDAAuD;AACvD,MAAM,UAAU,WAAW,CAAC,KAAgB,EAAE,OAA6B,EAAE;IAC3E,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,cAAc,GAAG,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;IAEjD,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8C,CAAC;IACvE,SAAS,MAAM,CAAC,IAAY;QAC1B,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;QAChB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;gBACzB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAAC,CAAC;QAC9C,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACtB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IAEzC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG;YAAE,SAAS;QAE3B,mEAAmE;QACnE,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACpB,WAAW,EAAE,CAAC;gBACd,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAAC,YAAY,EAAE,CAAC;oBAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAAC,CAAC;gBACpF,MAAM,EAAE,GAAe;oBACrB,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBAC5B,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc;oBAC9D,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,gCAAgC,IAAI,CAAC,IAAI,GAAG;oBACxE,QAAQ,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;iBACtD,CAAC;gBACF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAChB,SAAS;YACX,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACpB,WAAW,EAAE,CAAC;YACd,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAC,YAAY,EAAE,CAAC;gBAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YACpF,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC5B,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,IAAI,EAAE,aAAa;gBACnB,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,mBAAmB;gBAC/C,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,2DAA2D;QAC3D,IAAI,GAAG,GAAG,SAAS,GAAG,cAAc,IAAI,OAAO,CAAC,KAAK,GAAG,SAAS,GAAG,cAAc,EAAE,CAAC;YACnF,UAAU,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC5B,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,IAAI,EAAE,YAAY;gBAClB,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,cAAc,WAAW,yBAAyB;gBAC9E,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,KAAK,MAAM,EAAE,IAAI,MAAM;YAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;AAC3D,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,KAAgB,EAAE,KAAe;IAC9D,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACjE,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QACxD,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * v2.25.0 — LIVING SOUL CODEGRAPH public surface.
3
+ */
4
+ export * from "./types.js";
5
+ export { buildGraph, graphSignature } from "./builder.js";
6
+ export { writeSnapshot, readSnapshot, chainEdges, verifyChain, recordDrift, readDriftEvents, } from "./store.js";
7
+ export { merkleRoot, leafHash, rootsMatch, __EMPTY_ROOT_SENTINEL } from "./merkle.js";
8
+ export { query, neighbours, markVaccineWarning } from "./query.js";
9
+ export { detectDrift, edgesTouchedBy } from "./drift.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/codegraph/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EACL,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EACpD,WAAW,EAAE,eAAe,GAC7B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * v2.25.0 — LIVING SOUL CODEGRAPH public surface.
3
+ */
4
+ export * from "./types.js";
5
+ export { buildGraph, graphSignature } from "./builder.js";
6
+ export { writeSnapshot, readSnapshot, chainEdges, verifyChain, recordDrift, readDriftEvents, } from "./store.js";
7
+ export { merkleRoot, leafHash, rootsMatch, __EMPTY_ROOT_SENTINEL } from "./merkle.js";
8
+ export { query, neighbours, markVaccineWarning } from "./query.js";
9
+ export { detectDrift, edgesTouchedBy } from "./drift.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/codegraph/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EACL,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EACpD,WAAW,EAAE,eAAe,GAC7B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * v2.25.0 — Merkle root over the LIVING SOUL codegraph.
3
+ *
4
+ * Why: CodeGraph (the competitor) requires full re-index per machine.
5
+ * Mneme stores each edge with an HMAC link, then builds a Merkle tree
6
+ * over the canonical edge list. Two machines compare their root (32
7
+ * bytes); identical → graphs match without transmitting the full graph.
8
+ * Different → drill down via tree level until you find the divergent
9
+ * subtree. Cross-machine sync cost ≈ O(log N) instead of O(N).
10
+ *
11
+ * The tree is binary; leaves are SHA-256 of canonical edge JSON; inner
12
+ * nodes are SHA-256 of left || right concatenated. Empty graphs return
13
+ * a fixed sentinel hash.
14
+ */
15
+ import type { CodeEdge } from "./types.js";
16
+ /** Leaf hash for one edge (canonical JSON, sha256).
17
+ *
18
+ * Strips:
19
+ * - hmac — chain-position; varies per-position even with same content
20
+ * - lastSeen — wall-clock; varies across rebuilds of same structure
21
+ *
22
+ * So the leaf hash represents the STRUCTURAL identity of the edge
23
+ * (src, dst, kind, confidence, vendor attribution, vaccine warnings) —
24
+ * not the snapshot timestamp. This makes the Merkle root deterministic
25
+ * across rebuilds (and across machines for the same commit). */
26
+ export declare function leafHash(edge: CodeEdge): string;
27
+ /** Compute the Merkle root over a sorted edge list. */
28
+ export declare function merkleRoot(edges: CodeEdge[]): string;
29
+ /**
30
+ * Compare two Merkle roots. Identical roots = identical edge sets.
31
+ * Different roots = at least one edge differs.
32
+ *
33
+ * For partial-sync diagnostics, callers can drill into subtrees by
34
+ * exchanging the layer-1 hashes; this primitive returns the top-level
35
+ * verdict only.
36
+ */
37
+ export declare function rootsMatch(a: string, b: string): boolean;
38
+ /** Test-only sentinel. */
39
+ export declare const __EMPTY_ROOT_SENTINEL: string;
40
+ //# sourceMappingURL=merkle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../../src/codegraph/merkle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAS3C;;;;;;;;;gEASgE;AAChE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAI/C;AAED,uDAAuD;AACvD,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAepD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,0BAA0B;AAC1B,eAAO,MAAM,qBAAqB,QAAa,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * v2.25.0 — Merkle root over the LIVING SOUL codegraph.
3
+ *
4
+ * Why: CodeGraph (the competitor) requires full re-index per machine.
5
+ * Mneme stores each edge with an HMAC link, then builds a Merkle tree
6
+ * over the canonical edge list. Two machines compare their root (32
7
+ * bytes); identical → graphs match without transmitting the full graph.
8
+ * Different → drill down via tree level until you find the divergent
9
+ * subtree. Cross-machine sync cost ≈ O(log N) instead of O(N).
10
+ *
11
+ * The tree is binary; leaves are SHA-256 of canonical edge JSON; inner
12
+ * nodes are SHA-256 of left || right concatenated. Empty graphs return
13
+ * a fixed sentinel hash.
14
+ */
15
+ import { createHash } from "node:crypto";
16
+ import { canon } from "./types.js";
17
+ const EMPTY_ROOT = "e".repeat(64);
18
+ function sha(buf) {
19
+ return createHash("sha256").update(buf).digest("hex");
20
+ }
21
+ /** Leaf hash for one edge (canonical JSON, sha256).
22
+ *
23
+ * Strips:
24
+ * - hmac — chain-position; varies per-position even with same content
25
+ * - lastSeen — wall-clock; varies across rebuilds of same structure
26
+ *
27
+ * So the leaf hash represents the STRUCTURAL identity of the edge
28
+ * (src, dst, kind, confidence, vendor attribution, vaccine warnings) —
29
+ * not the snapshot timestamp. This makes the Merkle root deterministic
30
+ * across rebuilds (and across machines for the same commit). */
31
+ export function leafHash(edge) {
32
+ const { hmac: _h, lastSeen: _t, ...stable } = edge;
33
+ void _h;
34
+ void _t;
35
+ return sha(canon(stable));
36
+ }
37
+ /** Compute the Merkle root over a sorted edge list. */
38
+ export function merkleRoot(edges) {
39
+ if (edges.length === 0)
40
+ return EMPTY_ROOT;
41
+ // Sort by id for deterministic ordering across machines.
42
+ const sorted = [...edges].sort((a, b) => a.id.localeCompare(b.id));
43
+ let layer = sorted.map(leafHash);
44
+ while (layer.length > 1) {
45
+ const next = [];
46
+ for (let i = 0; i < layer.length; i += 2) {
47
+ const left = layer[i];
48
+ const right = i + 1 < layer.length ? layer[i + 1] : left; // duplicate last for odd count
49
+ next.push(sha(left + right));
50
+ }
51
+ layer = next;
52
+ }
53
+ return layer[0];
54
+ }
55
+ /**
56
+ * Compare two Merkle roots. Identical roots = identical edge sets.
57
+ * Different roots = at least one edge differs.
58
+ *
59
+ * For partial-sync diagnostics, callers can drill into subtrees by
60
+ * exchanging the layer-1 hashes; this primitive returns the top-level
61
+ * verdict only.
62
+ */
63
+ export function rootsMatch(a, b) {
64
+ return a === b && a !== EMPTY_ROOT;
65
+ }
66
+ /** Test-only sentinel. */
67
+ export const __EMPTY_ROOT_SENTINEL = EMPTY_ROOT;
68
+ //# sourceMappingURL=merkle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.js","sourceRoot":"","sources":["../../src/codegraph/merkle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAElC,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;;;gEASgE;AAChE,MAAM,UAAU,QAAQ,CAAC,IAAc;IACrC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACnD,KAAK,EAAE,CAAC;IAAC,KAAK,EAAE,CAAC;IACjB,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAC1C,yDAAyD;IACzD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;YACvB,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,+BAA+B;YAC1F,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC;QAC/B,CAAC;QACD,KAAK,GAAG,IAAI,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAE,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS,EAAE,CAAS;IAC7C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,0BAA0B;AAC1B,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * v2.25.0 — Query API for LIVING SOUL codegraph.
3
+ */
4
+ import type { CodeGraph, CodeEdge, CodeNode, QueryOptions, QueryResult } from "./types.js";
5
+ export declare function query(graph: CodeGraph, opts: QueryOptions): QueryResult;
6
+ /** Find all incoming and outgoing edges for a node. */
7
+ export declare function neighbours(graph: CodeGraph, nodeId: string): {
8
+ incoming: CodeEdge[];
9
+ outgoing: CodeEdge[];
10
+ node: CodeNode | null;
11
+ };
12
+ /** Mark an edge as a vaccine warning (e.g. an AI hallucinated this edge). */
13
+ export declare function markVaccineWarning(graph: CodeGraph, edgeId: string, reason: string): boolean;
14
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/codegraph/query.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE3F,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,WAAW,CA8BvE;AAED,uDAAuD;AACvD,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;CAAE,CASlI;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAM5F"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * v2.25.0 — Query API for LIVING SOUL codegraph.
3
+ */
4
+ export function query(graph, opts) {
5
+ let nodes = [...graph.nodes.values()];
6
+ let edges = [...graph.edges.values()];
7
+ if (opts.kind)
8
+ nodes = nodes.filter((n) => n.kind === opts.kind);
9
+ if (opts.pathContains) {
10
+ const p = opts.pathContains;
11
+ nodes = nodes.filter((n) => n.path.includes(p));
12
+ }
13
+ if (opts.symbol) {
14
+ const s = opts.symbol;
15
+ nodes = nodes.filter((n) => (n.symbol ?? "").toLowerCase().includes(s.toLowerCase()));
16
+ }
17
+ if (opts.srcIds) {
18
+ const set = new Set(opts.srcIds);
19
+ edges = edges.filter((e) => set.has(e.src));
20
+ }
21
+ if (opts.dstIds) {
22
+ const set = new Set(opts.dstIds);
23
+ edges = edges.filter((e) => set.has(e.dst));
24
+ }
25
+ if (opts.edgeKinds) {
26
+ const set = new Set(opts.edgeKinds);
27
+ edges = edges.filter((e) => set.has(e.kind));
28
+ }
29
+ if (opts.warningsOnly) {
30
+ edges = edges.filter((e) => e.vaccineWarning === true);
31
+ }
32
+ return { nodes, edges };
33
+ }
34
+ /** Find all incoming and outgoing edges for a node. */
35
+ export function neighbours(graph, nodeId) {
36
+ const node = graph.nodes.get(nodeId) ?? null;
37
+ const incoming = [];
38
+ const outgoing = [];
39
+ for (const e of graph.edges.values()) {
40
+ if (e.dst === nodeId)
41
+ incoming.push(e);
42
+ if (e.src === nodeId)
43
+ outgoing.push(e);
44
+ }
45
+ return { node, incoming, outgoing };
46
+ }
47
+ /** Mark an edge as a vaccine warning (e.g. an AI hallucinated this edge). */
48
+ export function markVaccineWarning(graph, edgeId, reason) {
49
+ const e = graph.edges.get(edgeId);
50
+ if (!e)
51
+ return false;
52
+ e.vaccineWarning = true;
53
+ e.warningReason = reason;
54
+ return true;
55
+ }
56
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/codegraph/query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * v2.25.0 — HMAC-chained storage for LIVING SOUL codegraph.
3
+ *
4
+ * Every edge gets an `hmac` field linking it to the previous edge in
5
+ * append order. Tampering with ANY edge (deleting / modifying /
6
+ * inserting) breaks the chain at that point. Receivers verify by
7
+ * re-deriving the chain from the canonical edge bodies.
8
+ *
9
+ * Storage layout:
10
+ * .mneme/codegraph/
11
+ * nodes.jsonl — append-only nodes
12
+ * edges.jsonl — append-only HMAC-chained edges
13
+ * state.json — { commit, builtAt, merkleRoot, stats }
14
+ * drift.jsonl — append-only drift events
15
+ */
16
+ import type { CodeEdge, CodeGraph, DriftEvent } from "./types.js";
17
+ /** Build HMAC-chained edges in-place — sets edge.hmac. */
18
+ export declare function chainEdges(edges: CodeEdge[]): void;
19
+ /** Verify the chain integrity of an edge list. */
20
+ export declare function verifyChain(edges: CodeEdge[]): {
21
+ ok: true;
22
+ } | {
23
+ ok: false;
24
+ firstBadIdx: number;
25
+ reason: string;
26
+ };
27
+ /** Write a full snapshot atomically. */
28
+ export declare function writeSnapshot(repoRoot: string, graph: CodeGraph): {
29
+ dir: string;
30
+ };
31
+ /** Read the persisted snapshot. Returns null if no graph has been built. */
32
+ export declare function readSnapshot(repoRoot: string): CodeGraph | null;
33
+ /** Append a drift event to the ledger. */
34
+ export declare function recordDrift(repoRoot: string, event: DriftEvent): void;
35
+ /** Read recent drift events. */
36
+ export declare function readDriftEvents(repoRoot: string, limit?: number): DriftEvent[];
37
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/codegraph/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAY,UAAU,EAAE,MAAM,YAAY,CAAC;AAqB5E,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAQlD;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAYhH;AAED,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAiBjF;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CA+B/D;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAGrE;AAED,gCAAgC;AAChC,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,UAAU,EAAE,CAU1E"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * v2.25.0 — HMAC-chained storage for LIVING SOUL codegraph.
3
+ *
4
+ * Every edge gets an `hmac` field linking it to the previous edge in
5
+ * append order. Tampering with ANY edge (deleting / modifying /
6
+ * inserting) breaks the chain at that point. Receivers verify by
7
+ * re-deriving the chain from the canonical edge bodies.
8
+ *
9
+ * Storage layout:
10
+ * .mneme/codegraph/
11
+ * nodes.jsonl — append-only nodes
12
+ * edges.jsonl — append-only HMAC-chained edges
13
+ * state.json — { commit, builtAt, merkleRoot, stats }
14
+ * drift.jsonl — append-only drift events
15
+ */
16
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync, } from "node:fs";
17
+ import { join } from "node:path";
18
+ import { createHmac } from "node:crypto";
19
+ import { canon } from "./types.js";
20
+ const HMAC_KEY = process.env["MNEME_CODEGRAPH_KEY"] ?? "mneme-codegraph-v1";
21
+ const CHAIN_SEED = "0".repeat(64);
22
+ function dirOf(repoRoot) {
23
+ return join(repoRoot, ".mneme", "codegraph");
24
+ }
25
+ function ensureDir(repoRoot) {
26
+ const d = dirOf(repoRoot);
27
+ if (!existsSync(d))
28
+ mkdirSync(d, { recursive: true });
29
+ return d;
30
+ }
31
+ /** Compute the next chain link. */
32
+ function nextLink(prev, body) {
33
+ return createHmac("sha256", HMAC_KEY).update(prev + "|" + canon(body)).digest("hex").slice(0, 32);
34
+ }
35
+ /** Build HMAC-chained edges in-place — sets edge.hmac. */
36
+ export function chainEdges(edges) {
37
+ let prev = CHAIN_SEED;
38
+ for (const e of edges) {
39
+ const { hmac: _h, ...stable } = e;
40
+ void _h;
41
+ prev = nextLink(prev, stable);
42
+ e.hmac = prev;
43
+ }
44
+ }
45
+ /** Verify the chain integrity of an edge list. */
46
+ export function verifyChain(edges) {
47
+ let prev = CHAIN_SEED;
48
+ for (let i = 0; i < edges.length; i++) {
49
+ const e = edges[i];
50
+ const { hmac, ...stable } = e;
51
+ const expected = nextLink(prev, stable);
52
+ if (expected !== hmac) {
53
+ return { ok: false, firstBadIdx: i, reason: `chain break at index ${i}: edge.id=${e.id}` };
54
+ }
55
+ prev = hmac;
56
+ }
57
+ return { ok: true };
58
+ }
59
+ /** Write a full snapshot atomically. */
60
+ export function writeSnapshot(repoRoot, graph) {
61
+ const d = ensureDir(repoRoot);
62
+ const nodes = [...graph.nodes.values()];
63
+ const edges = [...graph.edges.values()];
64
+ // edges must be chained before write
65
+ // (the builder is expected to have done this already; we re-chain to be safe)
66
+ chainEdges(edges);
67
+ writeFileSync(join(d, "nodes.jsonl"), nodes.map((n) => JSON.stringify(n)).join("\n") + (nodes.length ? "\n" : ""));
68
+ writeFileSync(join(d, "edges.jsonl"), edges.map((e) => JSON.stringify(e)).join("\n") + (edges.length ? "\n" : ""));
69
+ writeFileSync(join(d, "state.json"), JSON.stringify({
70
+ repoRoot: graph.repoRoot,
71
+ commit: graph.commit,
72
+ builtAt: graph.builtAt,
73
+ merkleRoot: graph.merkleRoot,
74
+ stats: graph.stats,
75
+ }, null, 2) + "\n");
76
+ return { dir: d };
77
+ }
78
+ /** Read the persisted snapshot. Returns null if no graph has been built. */
79
+ export function readSnapshot(repoRoot) {
80
+ const d = dirOf(repoRoot);
81
+ if (!existsSync(join(d, "state.json")))
82
+ return null;
83
+ const state = JSON.parse(readFileSync(join(d, "state.json"), "utf8"));
84
+ const nodesRaw = existsSync(join(d, "nodes.jsonl")) ? readFileSync(join(d, "nodes.jsonl"), "utf8").split("\n").filter(Boolean) : [];
85
+ const edgesRaw = existsSync(join(d, "edges.jsonl")) ? readFileSync(join(d, "edges.jsonl"), "utf8").split("\n").filter(Boolean) : [];
86
+ const nodes = new Map();
87
+ for (const line of nodesRaw) {
88
+ try {
89
+ const n = JSON.parse(line);
90
+ nodes.set(n.id, n);
91
+ }
92
+ catch { /* skip malformed */ }
93
+ }
94
+ const edges = new Map();
95
+ for (const line of edgesRaw) {
96
+ try {
97
+ const e = JSON.parse(line);
98
+ edges.set(e.id, e);
99
+ }
100
+ catch { /* skip */ }
101
+ }
102
+ return {
103
+ repoRoot,
104
+ commit: state.commit,
105
+ builtAt: state.builtAt,
106
+ nodes,
107
+ edges,
108
+ merkleRoot: state.merkleRoot,
109
+ stats: state.stats,
110
+ };
111
+ }
112
+ /** Append a drift event to the ledger. */
113
+ export function recordDrift(repoRoot, event) {
114
+ const d = ensureDir(repoRoot);
115
+ appendFileSync(join(d, "drift.jsonl"), JSON.stringify(event) + "\n");
116
+ }
117
+ /** Read recent drift events. */
118
+ export function readDriftEvents(repoRoot, limit = 50) {
119
+ const d = dirOf(repoRoot);
120
+ const p = join(d, "drift.jsonl");
121
+ if (!existsSync(p))
122
+ return [];
123
+ const lines = readFileSync(p, "utf8").split("\n").filter(Boolean);
124
+ const out = [];
125
+ for (const l of lines.slice(-limit)) {
126
+ try {
127
+ out.push(JSON.parse(l));
128
+ }
129
+ catch { /* skip */ }
130
+ }
131
+ return out;
132
+ }
133
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/codegraph/store.ts"],"names":[],"mappings":"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"}