@mneme-ai/xray 2.150.0 → 2.151.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.
@@ -0,0 +1,3 @@
1
+ import type { CouplingBlock } from "../types.js";
2
+ export declare function analyzeCoupling(repoPath: string, now: number, windowDays?: number): CouplingBlock;
3
+ //# sourceMappingURL=coupling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coupling.d.ts","sourceRoot":"","sources":["../../src/battery/coupling.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,aAAa,CAwC9F"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * CHANGE-COUPLING (temporal coupling) — files that keep changing together.
3
+ *
4
+ * Research: logical/evolutionary coupling (Gall et al.; D'Ambros & Lanza;
5
+ * Zimmermann et al. "mining version histories to guide changes"). Two files
6
+ * that change together far more often than chance share a HIDDEN dependency the
7
+ * type system can't see — the classic "I fixed A but forgot B" bug source.
8
+ *
9
+ * Deterministic: from `git log --name-only` (commit/tree metadata; no blob
10
+ * fetch). confidence(A,B) = coChanges / min(changes(A), changes(B)).
11
+ * "hidden" = the two files live in different directories (non-obvious coupling).
12
+ */
13
+ import { git, isGitRepo } from "../util.js";
14
+ const SKIP_DIR = /(^|\/)(node_modules|\.git|dist|build|vendor|\.next|coverage|__pycache__|\.venv|target)(\/|$)/;
15
+ const CODE_EXT = /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|c|h|cpp|cc|rb|php|cs|kt|swift|scala|vue|svelte)$/i;
16
+ const dir = (p) => { const i = p.lastIndexOf("/"); return i < 0 ? "" : p.slice(0, i); };
17
+ export function analyzeCoupling(repoPath, now, windowDays = 365) {
18
+ if (!isGitRepo(repoPath))
19
+ return { windowDays, pairs: [], note: "Not a git repository — coupling history unavailable." };
20
+ const since = new Date(now - windowDays * 86_400_000).toISOString();
21
+ // \x01 between commits → recover each commit's changed-file set
22
+ const raw = git(repoPath, ["log", "--since", since, "--no-merges", "--name-only", "--pretty=format:%x01"]);
23
+ if (!raw.trim())
24
+ return { windowDays, pairs: [], note: "No commit activity in the window." };
25
+ const fileCount = new Map();
26
+ const pairCount = new Map();
27
+ for (const block of raw.split("\x01")) {
28
+ const files = [...new Set(block.split("\n").map((s) => s.trim()).filter((f) => f && !SKIP_DIR.test(f) && CODE_EXT.test(f)))];
29
+ for (const f of files)
30
+ fileCount.set(f, (fileCount.get(f) ?? 0) + 1);
31
+ if (files.length < 2 || files.length > 40)
32
+ continue; // skip lone + sweeping commits for pairing
33
+ for (let i = 0; i < files.length; i++) {
34
+ for (let j = i + 1; j < files.length; j++) {
35
+ const k = files[i] < files[j] ? files[i] + "\x00" + files[j] : files[j] + "\x00" + files[i];
36
+ pairCount.set(k, (pairCount.get(k) ?? 0) + 1);
37
+ }
38
+ }
39
+ }
40
+ const pairs = [];
41
+ for (const [k, co] of pairCount) {
42
+ if (co < 5)
43
+ continue; // need support
44
+ const [a, b] = k.split("\x00");
45
+ const conf = co / Math.min(fileCount.get(a) ?? co, fileCount.get(b) ?? co);
46
+ if (conf < 0.5)
47
+ continue; // need strength
48
+ pairs.push({ a, b, coChanges: co, confidence: Math.round(conf * 100) / 100, hidden: dir(a) !== dir(b) });
49
+ }
50
+ // hidden (cross-dir) coupling first — that's the surprising, valuable kind
51
+ pairs.sort((x, y) => Number(y.hidden) - Number(x.hidden) || y.confidence - x.confidence || y.coChanges - x.coChanges);
52
+ const top = pairs[0];
53
+ return {
54
+ windowDays,
55
+ pairs: pairs.slice(0, 15),
56
+ note: top
57
+ ? `${top.a} ⇄ ${top.b} change together ${Math.round(top.confidence * 100)}% of the time${top.hidden ? " across different directories (hidden dependency)" : ""}.`
58
+ : "No strong change-coupling detected.",
59
+ };
60
+ }
61
+ //# sourceMappingURL=coupling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coupling.js","sourceRoot":"","sources":["../../src/battery/coupling.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,8 @@ type NpmMeta = Parameters<typeof depMortality.predictMortality>[0];
10
10
  export type MetaFetcher = (pkg: string, now: number) => Promise<NpmMeta | null>;
11
11
  /** Default: fetch the public npm registry document and derive mortality inputs. */
12
12
  export declare const defaultFetcher: MetaFetcher;
13
+ /** Classify an SPDX-ish license string into a commercial-risk band. */
14
+ export declare function licenseClass(lic: string): "permissive" | "weak-copyleft" | "strong-copyleft" | "unknown";
13
15
  export declare function analyzeDeps(repoPath: string, now: number, fetcher?: MetaFetcher): Promise<DepsBlock>;
14
16
  export {};
15
17
  //# sourceMappingURL=deps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../src/battery/deps.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAIhF,mFAAmF;AACnF,eAAO,MAAM,cAAc,EAAE,WA4C5B,CAAC;AAcF,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAA4B,GAAG,OAAO,CAAC,SAAS,CAAC,CAsC1H"}
1
+ {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../src/battery/deps.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAIhF,mFAAmF;AACnF,eAAO,MAAM,cAAc,EAAE,WA+C5B,CAAC;AAEF,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,eAAe,GAAG,iBAAiB,GAAG,SAAS,CAOxG;AAcD,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAA4B,GAAG,OAAO,CAAC,SAAS,CAAC,CA+C1H"}
@@ -39,6 +39,7 @@ export const defaultFetcher = async (pkg, now) => {
39
39
  monthsSinceFeatureRelease = (now - bestAt) / MONTH_MS;
40
40
  }
41
41
  const deprecated = !!(latest && doc.versions?.[latest]?.deprecated);
42
+ const license = (latest && doc.versions?.[latest]?.license) || doc.license || "";
42
43
  return {
43
44
  name: pkg,
44
45
  latestPublishedAt: latestAt,
@@ -46,12 +47,26 @@ export const defaultFetcher = async (pkg, now) => {
46
47
  monthsSinceFeatureRelease,
47
48
  deprecated,
48
49
  maintainerCount: Array.isArray(doc.maintainers) ? doc.maintainers.length : undefined,
50
+ license,
49
51
  };
50
52
  }
51
53
  catch {
52
54
  return null;
53
55
  }
54
56
  };
57
+ /** Classify an SPDX-ish license string into a commercial-risk band. */
58
+ export function licenseClass(lic) {
59
+ const s = (lic || "").toUpperCase();
60
+ if (!s || s === "UNLICENSED" || s === "SEE LICENSE" || s.includes("CUSTOM"))
61
+ return "unknown";
62
+ if (/\bAGPL|GPL-?[23]|GPLV[23]\b/.test(s) && !s.includes("LGPL"))
63
+ return "strong-copyleft";
64
+ if (/\bLGPL|MPL|EPL|CDDL|MS-RL\b/.test(s))
65
+ return "weak-copyleft";
66
+ if (/\bMIT|ISC|BSD|APACHE|UNLICENSE|0BSD|CC0|WTFPL|ZLIB|PYTHON|BLUEOAK\b/.test(s))
67
+ return "permissive";
68
+ return "unknown";
69
+ }
55
70
  function depNames(repoPath) {
56
71
  const raw = readText(join(repoPath, "package.json"));
57
72
  if (!raw)
@@ -68,12 +83,13 @@ function depNames(repoPath) {
68
83
  export async function analyzeDeps(repoPath, now, fetcher = defaultFetcher) {
69
84
  const names = depNames(repoPath);
70
85
  const byBand = { thriving: 0, healthy: 0, watch: 0, moribund: 0, dead: 0 };
86
+ const licenses = { permissive: 0, "weak-copyleft": 0, "strong-copyleft": 0, unknown: 0 };
71
87
  const atRisk = [];
88
+ const licenseFlags = [];
72
89
  if (names.length === 0) {
73
- return { total: 0, byBand, atRisk, partial: false, note: "No package.json dependencies found (non-npm repo or no deps)." };
90
+ return { total: 0, byBand, atRisk, licenses, licenseFlags, partial: false, note: "No package.json dependencies found (non-npm repo or no deps)." };
74
91
  }
75
92
  let partial = false;
76
- // bounded concurrency to be a polite registry citizen
77
93
  const LIMIT = 8;
78
94
  for (let i = 0; i < names.length; i += LIMIT) {
79
95
  const chunk = names.slice(i, i + LIMIT);
@@ -88,20 +104,31 @@ export async function analyzeDeps(repoPath, now, fetcher = defaultFetcher) {
88
104
  if (r.band === "watch" || r.band === "moribund" || r.band === "dead") {
89
105
  atRisk.push({ name: r.package, band: r.band, probability18mo: Math.round(r.probability18mo * 100) / 100, successor: meta.knownSubstitute ?? null });
90
106
  }
107
+ const lic = meta.license ?? "";
108
+ const cls = licenseClass(lic);
109
+ licenses[cls]++;
110
+ if (cls === "strong-copyleft" || cls === "weak-copyleft") {
111
+ licenseFlags.push({ name: meta.name, license: lic || "?", class: cls });
112
+ }
91
113
  }
92
114
  }
93
115
  atRisk.sort((a, b) => b.probability18mo - a.probability18mo);
116
+ licenseFlags.sort((a, b) => (a.class === "strong-copyleft" ? -1 : 1) - (b.class === "strong-copyleft" ? -1 : 1));
94
117
  const danger = byBand.moribund + byBand.dead;
118
+ const copyleft = licenses["strong-copyleft"] + licenses["weak-copyleft"];
119
+ const parts = [];
120
+ if (danger > 0)
121
+ parts.push(`${danger} dying (moribund/dead) — plan replacements`);
122
+ if (copyleft > 0)
123
+ parts.push(`${copyleft} copyleft-licensed (commercial-use review)`);
95
124
  return {
96
125
  total: names.length,
97
126
  byBand,
98
127
  atRisk: atRisk.slice(0, 20),
128
+ licenses,
129
+ licenseFlags: licenseFlags.slice(0, 15),
99
130
  partial,
100
- note: danger > 0
101
- ? `${danger} depend<x>${danger === 1 ? "y is" : "ies are"}</x> dying (moribund/dead). Plan replacements.`.replace(/<x>|<\/x>/g, "")
102
- : partial
103
- ? "Some packages could not be reached on the npm registry (counted as unknown)."
104
- : "No dying dependencies detected.",
131
+ note: parts.length ? parts.join("; ") + "." : partial ? "Some packages could not be reached on the npm registry." : "No dying or copyleft-risk dependencies.",
105
132
  };
106
133
  }
107
134
  //# sourceMappingURL=deps.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/battery/deps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/battery/deps.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAMjC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;AAE7C,mFAAmF;AACnF,MAAM,CAAC,MAAM,cAAc,GAAgB,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAC5D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,8BAA8B,kBAAkB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE;YACnG,OAAO,EAAE,EAAE,MAAM,EAAE,uDAAuD,EAAE;SAC7E,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAM5B,CAAC;QACF,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QACxC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACnD,MAAM,iBAAiB,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAEzF,6EAA6E;QAC7E,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QACjD,IAAI,yBAA6C,CAAC;QAClD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YACnE,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBACjE,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC;oBAChE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;oBACpC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM;wBAAE,MAAM,GAAG,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;YACD,IAAI,MAAM,GAAG,CAAC;gBAAE,yBAAyB,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC;QACxE,CAAC;QACD,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;QACjF,OAAO;YACL,IAAI,EAAE,GAAG;YACT,iBAAiB,EAAE,QAAQ;YAC3B,iBAAiB;YACjB,yBAAyB;YACzB,UAAU;YACV,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;YACpF,OAAO;SAC0B,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,YAAY,IAAI,CAAC,KAAK,aAAa,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9F,IAAI,6BAA6B,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,iBAAiB,CAAC;IAC3F,IAAI,6BAA6B,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,eAAe,CAAC;IAClE,IAAI,qEAAqE,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,YAAY,CAAC;IACvG,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,QAAQ,CAAC,QAAgB;IAChC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC;IACrD,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwF,CAAC;QACnH,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACnH,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,GAAW,EAAE,UAAuB,cAAc;IACpG,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,MAAM,GAAwB,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAChG,MAAM,QAAQ,GAA0B,EAAE,UAAU,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAChH,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,MAAM,YAAY,GAA8B,EAAE,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,+DAA+D,EAAE,CAAC;IACrJ,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,KAAK,GAAG,CAAC,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,EAAE,CAAC;gBAAC,OAAO,GAAG,IAAI,CAAC;gBAAC,SAAS;YAAC,CAAC;YACxC,MAAM,CAAC,GAAG,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACrE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC,CAAC;YACtJ,CAAC;YACD,MAAM,GAAG,GAAI,IAAuC,CAAC,OAAO,IAAI,EAAE,CAAC;YACnE,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;YAC9B,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAChB,IAAI,GAAG,KAAK,iBAAiB,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;gBACzD,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;IAC7D,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjH,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;IAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,iBAAiB,CAAC,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;IACzE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,4CAA4C,CAAC,CAAC;IAClF,IAAI,QAAQ,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,4CAA4C,CAAC,CAAC;IACtF,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC3B,QAAQ;QACR,YAAY,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QACvC,OAAO;QACP,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,yDAAyD,CAAC,CAAC,CAAC,yCAAyC;KAC9J,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"hotspots.d.ts","sourceRoot":"","sources":["../../src/battery/hotspots.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,aAAa,CAqC9F"}
1
+ {"version":3,"file":"hotspots.d.ts","sourceRoot":"","sources":["../../src/battery/hotspots.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,SAAM,GAAG,aAAa,CA4D9F"}
@@ -5,16 +5,15 @@
5
5
  * that are BOTH changed often AND large/complex. This is well established —
6
6
  * code churn predicts defects (Nagappan & Ball, ICSE'05), and "hotspots" =
7
7
  * change-frequency × complexity surface the highest-ROI refactoring targets
8
- * (Tornhill, *Your Code as a Crime Scene*; D'Ambros & Lanza, evolutionary
9
- * measures). We compute it 100% deterministically:
8
+ * (Tornhill, *Your Code as a Crime Scene*; D'Ambros & Lanza). We compute it
9
+ * 100% deterministically:
10
10
  *
11
11
  * change-frequency ← `git log --name-only` over a window (no blob fetch —
12
12
  * works on a blobless clone; uses commit/tree metadata)
13
13
  * complexity proxy ← current lines-of-code of the file (HEAD blob)
14
14
  * hotspot score ← changeCount × loc, ranked
15
- *
16
- * The output answers "where do I refactor first?" — a question no secret scanner
17
- * or dependency checker answers, and one a CTO actually pays for.
15
+ * expert ← the author with the most commits to the file (who to ask)
16
+ * trend ← commits per time bucket (oldest→newest), for a sparkline
18
17
  */
19
18
  import { git, readText, isGitRepo } from "../util.js";
20
19
  import { join } from "node:path";
@@ -22,39 +21,79 @@ const SKIP_DIR = /(^|\/)(node_modules|\.git|dist|build|vendor|\.next|coverage|__
22
21
  const CODE_EXT = /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|c|h|cpp|cc|rb|php|cs|kt|swift|scala|vue|svelte)$/i;
23
22
  export function analyzeHotspots(repoPath, now, windowDays = 365) {
24
23
  if (!isGitRepo(repoPath)) {
25
- return { windowDays, filesConsidered: 0, hotspots: [], note: "Not a git repository — hotspot history unavailable." };
24
+ return { windowDays, filesConsidered: 0, hotspots: [], trend: [], note: "Not a git repository — hotspot history unavailable." };
26
25
  }
27
26
  const since = new Date(now - windowDays * 86_400_000).toISOString();
28
- // empty pretty format output is just the changed file paths, one per line,
29
- // per commit. Counting occurrences = how many commits touched each file.
30
- const raw = git(repoPath, ["log", "--since", since, "--no-merges", "--name-only", "--pretty=format:"]);
27
+ // per commit: "C<TAB><email>" then changed file paths. One pass → change
28
+ // frequency per file + the dominant author per file (the "expert").
29
+ const raw = git(repoPath, ["log", "--since", since, "--no-merges", "--name-only", "--pretty=format:C%x09%ae"]);
31
30
  if (!raw.trim())
32
- return { windowDays, filesConsidered: 0, hotspots: [], note: "No commit activity in the window." };
31
+ return { windowDays, filesConsidered: 0, hotspots: [], trend: [], note: "No commit activity in the window." };
33
32
  const changes = new Map();
33
+ const authorsByFile = new Map();
34
+ let curAuthor = "";
34
35
  for (const line of raw.split("\n")) {
36
+ if (line.startsWith("C\t")) {
37
+ curAuthor = line.slice(2).trim();
38
+ continue;
39
+ }
35
40
  const f = line.trim();
36
41
  if (!f || SKIP_DIR.test(f) || !CODE_EXT.test(f))
37
42
  continue;
38
43
  changes.set(f, (changes.get(f) ?? 0) + 1);
44
+ if (curAuthor) {
45
+ let m = authorsByFile.get(f);
46
+ if (!m) {
47
+ m = new Map();
48
+ authorsByFile.set(f, m);
49
+ }
50
+ m.set(curAuthor, (m.get(curAuthor) ?? 0) + 1);
51
+ }
39
52
  }
40
53
  if (changes.size === 0)
41
- return { windowDays, filesConsidered: 0, hotspots: [], note: "No source-file changes in the window." };
42
- // join change-frequency with current size (complexity proxy). Only read LOC
43
- // for the most-changed files (bounded work).
54
+ return { windowDays, filesConsidered: 0, hotspots: [], trend: [], note: "No source-file changes in the window." };
44
55
  const ranked = [...changes.entries()].sort((a, b) => b[1] - a[1]).slice(0, 80);
45
56
  const rows = ranked.map(([file, changeCount]) => {
46
57
  const txt = readText(join(repoPath, file));
47
58
  const loc = txt ? txt.split("\n").length : 0;
48
- return { file, changes: changeCount, loc, score: changeCount * loc };
59
+ const m = authorsByFile.get(file);
60
+ let expert = "", top = 0, authors = 0;
61
+ if (m) {
62
+ authors = m.size;
63
+ for (const [a, c] of m)
64
+ if (c > top) {
65
+ top = c;
66
+ expert = a;
67
+ }
68
+ }
69
+ return { file, changes: changeCount, loc, score: changeCount * loc, expert, authors };
49
70
  }).filter((r) => r.loc > 0);
50
71
  rows.sort((a, b) => b.score - a.score);
72
+ // trend: commits per equal bucket over the window (oldest → newest)
73
+ const BUCKETS = 8;
74
+ const trend = new Array(BUCKETS).fill(0);
75
+ const winMs = windowDays * 86_400_000;
76
+ const tsRaw = git(repoPath, ["log", "--since", since, "--no-merges", "--pretty=format:%ct"]);
77
+ for (const l of tsRaw.split("\n")) {
78
+ const sec = parseInt(l.trim(), 10);
79
+ if (!Number.isFinite(sec))
80
+ continue;
81
+ const ageMs = now - sec * 1000;
82
+ let idx = BUCKETS - 1 - Math.floor((ageMs / winMs) * BUCKETS);
83
+ if (idx < 0)
84
+ idx = 0;
85
+ if (idx > BUCKETS - 1)
86
+ idx = BUCKETS - 1;
87
+ trend[idx]++;
88
+ }
51
89
  const top = rows[0];
52
90
  return {
53
91
  windowDays,
54
92
  filesConsidered: changes.size,
55
93
  hotspots: rows.slice(0, 15),
94
+ trend,
56
95
  note: top
57
- ? `Hotspot: ${top.file} — changed ${top.changes}× and ${top.loc} lines. High churn × size = where defects and refactoring ROI concentrate (behavioral code analysis).`
96
+ ? `Hotspot: ${top.file} — changed ${top.changes}× and ${top.loc} lines${top.expert ? ` (ask: ${top.expert})` : ""}. High churn × size = where defects and refactoring ROI concentrate.`
58
97
  : "No hotspots surfaced.",
59
98
  };
60
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hotspots.js","sourceRoot":"","sources":["../../src/battery/hotspots.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hotspots.js","sourceRoot":"","sources":["../../src/battery/hotspots.ts"],"names":[],"mappings":"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"}
package/dist/bin.js CHANGED
@@ -12,13 +12,40 @@ import { buildXRay } from "./engine.js";
12
12
  import { sealXRay, verifyXRay } from "./sign.js";
13
13
  import { xrayLeaksRaw } from "./privacy.js";
14
14
  import { publishReport } from "./publish.js";
15
+ import { runBridge } from "./bridge.js";
15
16
  import { existsSync } from "node:fs";
17
+ import { spawnSync } from "node:child_process";
16
18
  function flagVal(args, name) {
17
19
  const i = args.indexOf(name);
18
20
  return i >= 0 && args[i + 1] && !args[i + 1].startsWith("--") ? args[i + 1] : undefined;
19
21
  }
20
22
  async function main() {
21
23
  const args = process.argv.slice(2);
24
+ // `bridge` — run the local agent so the website can scan local folders
25
+ if (args[0] === "bridge") {
26
+ runBridge(parseInt(flagVal(args, "--port") || process.env.XRAY_BRIDGE_PORT || "7799", 10));
27
+ return;
28
+ }
29
+ // `ci-gate` — fail CI if a changed file is a high hotspot (enterprise gate)
30
+ if (args[0] === "ci-gate") {
31
+ const path = args.find((a, i) => i > 0 && !a.startsWith("--") && a !== flagVal(args, "--changed")) || ".";
32
+ const threshold = parseInt(flagVal(args, "--threshold") || "3", 10); // top-N hotspots are "high"
33
+ const report = await buildXRay({ repoPath: path });
34
+ const top = report.hotspots.hotspots.slice(0, threshold).map((h) => h.file);
35
+ let changed = (flagVal(args, "--changed") || "").split(",").map((s) => s.trim()).filter(Boolean);
36
+ if (changed.length === 0) {
37
+ // derive from the last commit if not supplied
38
+ const r = spawnSync("git", ["diff", "--name-only", "HEAD~1", "HEAD"], { cwd: path, encoding: "utf8" });
39
+ changed = (r.stdout || "").split("\n").map((s) => s.trim()).filter(Boolean);
40
+ }
41
+ const hits = changed.filter((f) => top.includes(f));
42
+ if (hits.length) {
43
+ process.stdout.write(`⚠️ CI GATE: changed files touch top-${threshold} hotspots — review carefully:\n${hits.map((h) => " 🔥 " + h).join("\n")}\n`);
44
+ process.exit(2);
45
+ }
46
+ process.stdout.write(`✓ CI GATE: no changed file is a top-${threshold} hotspot.\n`);
47
+ return;
48
+ }
22
49
  const target = args.find((a) => !a.startsWith("--") && a !== flagVal(args, "--server") && a !== flagVal(args, "--token"));
23
50
  const asJson = args.includes("--json");
24
51
  const noSign = args.includes("--no-sign");
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runBridge(port?: number): void;
2
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AA6CA,wBAAgB,SAAS,CAAC,IAAI,SAAO,GAAG,IAAI,CAoC3C"}
package/dist/bridge.js ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * THE LOCAL BRIDGE — how the cloud website reads a LOCAL folder without the
3
+ * code ever leaving the machine.
4
+ *
5
+ * The user runs `npx @mneme-ai/xray bridge` on their own machine. It starts a
6
+ * tiny server bound to 127.0.0.1 only. The website (https://xray.mneme-ai.space)
7
+ * fetches it over localhost — browsers exempt http://localhost from mixed-content
8
+ * blocking, so an https page may call it. The bridge analyses the local path and
9
+ * returns ONLY a signed, raw-free report. The cloud server is never involved;
10
+ * the source never moves. The page renders the report exactly like a cloud scan.
11
+ *
12
+ * GET /bridge/ping → { ok, version } (the page auto-detects it)
13
+ * POST /bridge/xray { path } → build local X-Ray → raw-free gate → sign → return
14
+ */
15
+ import { createServer } from "node:http";
16
+ import { existsSync, readFileSync } from "node:fs";
17
+ import { dirname, join } from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+ import { buildXRay } from "./engine.js";
20
+ import { sealXRay } from "./sign.js";
21
+ import { xrayLeaksRaw } from "./privacy.js";
22
+ const ALLOW = [
23
+ /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/,
24
+ /^https:\/\/xray\.mneme-ai\.space$/,
25
+ /^https:\/\/xray\.161\.35\.122\.73\.nip\.io$/,
26
+ ];
27
+ function version() {
28
+ try {
29
+ const p = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
30
+ return JSON.parse(readFileSync(p, "utf8")).version ?? "0.0.0";
31
+ }
32
+ catch {
33
+ return "0.0.0";
34
+ }
35
+ }
36
+ function cors(res, origin) {
37
+ const ok = origin && ALLOW.some((re) => re.test(origin));
38
+ res.setHeader("access-control-allow-origin", ok ? origin : "https://xray.mneme-ai.space");
39
+ res.setHeader("access-control-allow-methods", "GET,POST,OPTIONS");
40
+ res.setHeader("access-control-allow-headers", "content-type");
41
+ res.setHeader("vary", "origin");
42
+ }
43
+ function json(res, status, body) {
44
+ res.writeHead(status, { "content-type": "application/json; charset=utf-8" });
45
+ res.end(JSON.stringify(body));
46
+ }
47
+ export function runBridge(port = 7799) {
48
+ const server = createServer(async (req, res) => {
49
+ cors(res, req.headers.origin);
50
+ if (req.method === "OPTIONS") {
51
+ res.writeHead(204);
52
+ res.end();
53
+ return;
54
+ }
55
+ const url = new URL(req.url || "/", "http://127.0.0.1");
56
+ if (req.method === "GET" && url.pathname === "/bridge/ping") {
57
+ return json(res, 200, { ok: true, agent: "mneme-xray-bridge", version: version() });
58
+ }
59
+ if (req.method === "POST" && url.pathname === "/bridge/xray") {
60
+ let body = "";
61
+ req.on("data", (c) => (body += c));
62
+ req.on("end", async () => {
63
+ try {
64
+ const { path } = JSON.parse(body || "{}");
65
+ if (!path || !existsSync(path))
66
+ return json(res, 400, { error: "path does not exist on this machine: " + (path || "(empty)") });
67
+ const report = await buildXRay({ repoPath: path });
68
+ if (xrayLeaksRaw(report).leaks)
69
+ return json(res, 500, { error: "internal: raw-free gate" });
70
+ const signed = sealXRay(existsSync(path) ? path : process.cwd(), report);
71
+ process.stdout.write(` ✓ local X-Ray: ${path} → grade ${report.summary.grade} (source never left this machine)\n`);
72
+ return json(res, 200, signed);
73
+ }
74
+ catch (e) {
75
+ return json(res, 500, { error: e.message.slice(0, 300) });
76
+ }
77
+ });
78
+ return;
79
+ }
80
+ json(res, 404, { error: "not found" });
81
+ });
82
+ server.listen(port, "127.0.0.1", () => {
83
+ process.stdout.write(`\n 🖥 Mneme X-Ray — LOCAL BRIDGE running at http://127.0.0.1:${port}\n` +
84
+ ` Open https://xray.mneme-ai.space → it auto-detects this bridge → scan any local folder.\n` +
85
+ ` Your source never leaves this machine. Ctrl-C to stop.\n\n`);
86
+ });
87
+ process.on("SIGINT", () => { server.close(() => process.exit(0)); });
88
+ }
89
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AAYA,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE;AAElE;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAgBrD"}
1
+ {"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AAaA,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE;AAElE;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAgBrD"}
package/dist/clone.js CHANGED
@@ -7,7 +7,8 @@ import { spawnSync } from "node:child_process";
7
7
  import { mkdtempSync, rmSync } from "node:fs";
8
8
  import { tmpdir } from "node:os";
9
9
  import { join } from "node:path";
10
- const ALLOWED = /^https:\/\/(github\.com|gitlab\.com|bitbucket\.org)\/[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+(\.git)?\/?$/;
10
+ // owner/repo, OR deeper (GitLab nested subgroups: group/subgroup/repo). >=2 segments.
11
+ const ALLOWED = /^https:\/\/(github\.com|gitlab\.com|bitbucket\.org)\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)+\/?$/;
11
12
  export function isAllowedPublicUrl(url) {
12
13
  if (/@|:\/\/[^/]*:[^/]*@/.test(url.replace("https://", "")))
13
14
  return false; // reject embedded creds
package/dist/clone.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"clone.js","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,OAAO,GAAG,mGAAmG,CAAC;AAEpH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,IAAI,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,wBAAwB;IACnG,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AAClC,CAAC;AAID;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAC;IAC7G,CAAC;IACD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,iBAAiB,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE;QAC3G,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KAC5B,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7G,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,MAAM,IAAI,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"clone.js","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,sFAAsF;AACtF,MAAM,OAAO,GAAG,gGAAgG,CAAC;AAEjH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,IAAI,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,wBAAwB;IACnG,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AAClC,CAAC;AAID;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAC;IAC7G,CAAC;IACD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,iBAAiB,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE;QAC3G,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KAC5B,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7G,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,MAAM,IAAI,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAsB,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASlE,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,+CAA+C;IAC/C,UAAU,CAAC,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAiDvE"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAsB,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAUlE,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,+CAA+C;IAC/C,UAAU,CAAC,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAkDvE"}
package/dist/engine.js CHANGED
@@ -12,6 +12,7 @@ import { analyzeBusFactor } from "./battery/busfactor.js";
12
12
  import { analyzeAge } from "./battery/age.js";
13
13
  import { analyzeComplexity } from "./battery/complexity.js";
14
14
  import { analyzeHotspots } from "./battery/hotspots.js";
15
+ import { analyzeCoupling } from "./battery/coupling.js";
15
16
  import { shallowClone } from "./clone.js";
16
17
  import { headCommit, repoNameFromUrl, repoNameFromPath } from "./util.js";
17
18
  export async function buildXRay(opts) {
@@ -43,8 +44,9 @@ export async function buildXRay(opts) {
43
44
  const age = analyzeAge(repoPath, now);
44
45
  const complexity = analyzeComplexity(repoPath, maxFiles);
45
46
  const hotspots = analyzeHotspots(repoPath, now);
46
- const summary = grade({ deps, secrets, busFactor, age, complexity, hotspots });
47
- const blocks = { deps, secrets, busFactor, age, complexity, hotspots };
47
+ const coupling = analyzeCoupling(repoPath, now);
48
+ const summary = grade({ deps, secrets, busFactor, age, complexity, hotspots, coupling });
49
+ const blocks = { deps, secrets, busFactor, age, complexity, hotspots, coupling };
48
50
  const fingerprint = createHash("sha256")
49
51
  .update(JSON.stringify({ subject: { repoName: subject.repoName, commitHash: subject.commitHash }, blocks }))
50
52
  .digest("hex");
@@ -82,14 +84,19 @@ function grade(b) {
82
84
  ? `🔑 No credential patterns in production code${exTail}.`
83
85
  : `🔑 ${b.secrets.totalFindings} credential-pattern match(es) in production code — review${exTail}.`);
84
86
  }
85
- // deps
87
+ // deps (mortality + license)
86
88
  if (b.deps.total > 0) {
87
89
  signalsRun++;
88
90
  const dying = b.deps.byBand.moribund + b.deps.byBand.dead;
91
+ const strongCopyleft = b.deps.licenses["strong-copyleft"];
89
92
  score -= Math.min(20, dying * 5);
93
+ score -= Math.min(10, strongCopyleft * 5); // GPL/AGPL in a commercial codebase = real risk
90
94
  bullets.push(dying === 0
91
95
  ? `📦 ${b.deps.total} deps, none dying.`
92
96
  : `💀 ${dying} of ${b.deps.total} deps are dying${b.deps.atRisk[0]?.successor ? ` (e.g. ${b.deps.atRisk[0].name} → ${b.deps.atRisk[0].successor})` : ""}.`);
97
+ const copyleft = b.deps.licenses["strong-copyleft"] + b.deps.licenses["weak-copyleft"];
98
+ if (copyleft > 0)
99
+ bullets.push(`⚖️ ${copyleft} copyleft-licensed dep(s)${b.deps.licenseFlags[0] ? ` (e.g. ${b.deps.licenseFlags[0].name}: ${b.deps.licenseFlags[0].license})` : ""} — review for commercial use.`);
93
100
  }
94
101
  // bus factor
95
102
  if (b.busFactor.authors > 0) {
@@ -126,7 +133,13 @@ function grade(b) {
126
133
  if (b.hotspots.hotspots.length > 0) {
127
134
  signalsRun++;
128
135
  const h = b.hotspots.hotspots[0];
129
- bullets.push(`🔥 Refactor first: ${h.file} — changed ${h.changes}× · ${h.loc} lines (churn × size).`);
136
+ bullets.push(`🔥 Refactor first: ${h.file} — changed ${h.changes}× · ${h.loc} lines${h.expert ? ` (ask: ${h.expert})` : ""}.`);
137
+ }
138
+ // change-coupling — informational (hidden dependencies)
139
+ if (b.coupling.pairs.length > 0) {
140
+ signalsRun++;
141
+ const c = b.coupling.pairs[0];
142
+ bullets.push(`🔗 ${c.a} ⇄ ${c.b} change together ${Math.round(c.confidence * 100)}%${c.hidden ? " (hidden cross-dir coupling)" : ""}.`);
130
143
  }
131
144
  score = Math.max(0, Math.min(100, Math.round(score)));
132
145
  const g = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : score >= 55 ? "D" : "F";
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"gauntlet.d.ts","sourceRoot":"","sources":["../src/gauntlet.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,0BAA0B,EAAE,OAAO,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAkBD,wBAAgB,YAAY,IAAI,YAAY,CAyB3C"}
1
+ {"version":3,"file":"gauntlet.d.ts","sourceRoot":"","sources":["../src/gauntlet.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,YAAY;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,0BAA0B,EAAE,OAAO,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAmBD,wBAAgB,YAAY,IAAI,YAAY,CAyB3C"}
package/dist/gauntlet.js CHANGED
@@ -11,12 +11,13 @@ function cleanFixture() {
11
11
  subject: { kind: "git-url", ref: "https://github.com/acme/widget", repoName: "acme/widget", commitHash: "abc123def456" },
12
12
  generatedAt: "2026-01-01T00:00:00.000Z",
13
13
  summary: { headline: "Mixed", grade: "C", signalsRun: 5, bullets: ["🔑 No credential patterns found in tracked files."] },
14
- deps: { total: 12, byBand: { thriving: 8, healthy: 2, watch: 1, moribund: 1, dead: 0 }, atRisk: [{ name: "request", band: "dead", probability18mo: 0.9, successor: "got" }], partial: false, note: "1 dying." },
14
+ deps: { total: 12, byBand: { thriving: 8, healthy: 2, watch: 1, moribund: 1, dead: 0 }, atRisk: [{ name: "request", band: "dead", probability18mo: 0.9, successor: "got" }], licenses: { permissive: 11, "weak-copyleft": 0, "strong-copyleft": 1, unknown: 0 }, licenseFlags: [{ name: "some-gpl-lib", license: "GPL-3.0", class: "strong-copyleft" }], partial: false, note: "1 dying." },
15
15
  secrets: { filesScanned: 40, totalFindings: 0, excludedTestHits: 3, byKind: {}, hits: [], worstVerdict: "ALLOW", note: "clean" },
16
16
  busFactor: { authors: 5, singleOwnerFilePct: 22.5, fragileFiles: [{ file: "src/core.ts", topAuthorShare: 0.9, commits: 30 }], topContributorShare: 41.2, busFactor: 2, note: "5 authors" },
17
17
  age: { bornAt: "2020-01-01", lastCommitAt: "2026-01-01", lifespan: "6 years", lifespanDays: 2192, totalCommits: 1200, totalAuthors: 5, dormant: false, vitality: "active", note: "active" },
18
18
  complexity: { filesAnalysed: 40, totalSymbols: 320, hotspots: [{ file: "src/core.ts", symbol: "function handleRequest(req, res)", bodyLines: 180, startLine: 12 }], maxDepth: 4, note: "hotspot" },
19
- hotspots: { windowDays: 365, filesConsidered: 40, hotspots: [{ file: "src/core.ts", changes: 30, loc: 400, score: 12000 }], note: "Hotspot: src/core.ts — changed 30× and 400 lines." },
19
+ hotspots: { windowDays: 365, filesConsidered: 40, hotspots: [{ file: "src/core.ts", changes: 30, loc: 400, score: 12000, expert: "alice@acme.dev", authors: 3 }], trend: [2, 4, 6, 3, 8, 5, 7, 9], note: "Hotspot: src/core.ts — changed 30× and 400 lines." },
20
+ coupling: { windowDays: 365, pairs: [{ a: "src/core.ts", b: "src/api/routes.ts", coChanges: 12, confidence: 0.8, hidden: true }], note: "src/core.ts ⇄ src/api/routes.ts change together 80%." },
20
21
  fingerprint: "deadbeef",
21
22
  };
22
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gauntlet.js","sourceRoot":"","sources":["../src/gauntlet.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gauntlet.js","sourceRoot":"","sources":["../src/gauntlet.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -18,4 +18,7 @@ export { defaultFetcher, type MetaFetcher } from "./battery/deps.js";
18
18
  export { publishReport, type PublishResult } from "./publish.js";
19
19
  export { createXRayServer } from "./server.js";
20
20
  export { CosmicMonitor, computeStatus, cosmicBadgeSvg, type CosmicStatus, type Sample } from "./cosmic.js";
21
+ export { runBridge } from "./bridge.js";
22
+ export { analyzeCoupling } from "./battery/coupling.js";
23
+ export { licenseClass } from "./battery/deps.js";
21
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC3G,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -18,4 +18,7 @@ export { defaultFetcher } from "./battery/deps.js";
18
18
  export { publishReport } from "./publish.js";
19
19
  export { createXRayServer } from "./server.js";
20
20
  export { CosmicMonitor, computeStatus, cosmicBadgeSvg } from "./cosmic.js";
21
+ export { runBridge } from "./bridge.js";
22
+ export { analyzeCoupling } from "./battery/coupling.js";
23
+ export { licenseClass } from "./battery/deps.js";
21
24
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAqB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAoB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAqB,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,cAAc,EAAoB,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAkC,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAqB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAoB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAqB,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,cAAc,EAAoB,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAkC,MAAM,aAAa,CAAC;AAC3G,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -21,7 +21,7 @@ export interface XRaySubject {
21
21
  /** HEAD commit the report was computed at (provenance). */
22
22
  commitHash: string;
23
23
  }
24
- /** Dependency mortality "which of your dependencies are dying". */
24
+ /** Dependency mortality + license/supply-chain risk. */
25
25
  export interface DepsBlock {
26
26
  total: number;
27
27
  byBand: Record<"thriving" | "healthy" | "watch" | "moribund" | "dead", number>;
@@ -32,10 +32,31 @@ export interface DepsBlock {
32
32
  probability18mo: number;
33
33
  successor: string | null;
34
34
  }>;
35
+ /** License class counts (permissive / copyleft / unknown). */
36
+ licenses: Record<"permissive" | "weak-copyleft" | "strong-copyleft" | "unknown", number>;
37
+ /** Deps whose license is copyleft/unknown — a commercial-use review flag. */
38
+ licenseFlags: Array<{
39
+ name: string;
40
+ license: string;
41
+ class: string;
42
+ }>;
35
43
  /** True when npm metadata could not be fetched for some deps (honest degradation). */
36
44
  partial: boolean;
37
45
  note: string;
38
46
  }
47
+ /** Change-coupling (temporal coupling) — files that change together. */
48
+ export interface CouplingBlock {
49
+ windowDays: number;
50
+ /** Strongest co-change pairs. hidden = different directories (a non-obvious dependency). */
51
+ pairs: Array<{
52
+ a: string;
53
+ b: string;
54
+ coChanges: number;
55
+ confidence: number;
56
+ hidden: boolean;
57
+ }>;
58
+ note: string;
59
+ }
39
60
  /** Secret / credential leak scan (values are NEVER stored — only kind + count + location). */
40
61
  export interface SecretsBlock {
41
62
  filesScanned: number;
@@ -96,7 +117,9 @@ export interface ComplexityBlock {
96
117
  maxDepth: number;
97
118
  note: string;
98
119
  }
99
- /** Behavioral hotspots — change-frequency × size (refactor-ROI targets). */
120
+ /** Behavioral hotspots — change-frequency × size (refactor-ROI targets).
121
+ * Each hotspot also names the primary author (who to ask = onboarding signal),
122
+ * and `trend` is per-bucket commit activity (oldest→newest) for a sparkline. */
100
123
  export interface HotspotsBlock {
101
124
  windowDays: number;
102
125
  filesConsidered: number;
@@ -105,7 +128,11 @@ export interface HotspotsBlock {
105
128
  changes: number;
106
129
  loc: number;
107
130
  score: number;
131
+ expert: string;
132
+ authors: number;
108
133
  }>;
134
+ /** commit counts per equal time bucket, oldest → newest (sparkline). */
135
+ trend: number[];
109
136
  note: string;
110
137
  }
111
138
  export interface XRaySummary {
@@ -127,6 +154,7 @@ export interface XRayReport {
127
154
  age: AgeBlock;
128
155
  complexity: ComplexityBlock;
129
156
  hotspots: HotspotsBlock;
157
+ coupling: CouplingBlock;
130
158
  /** sha256 over the canonicalised metric blocks — a tamper-evident content id. */
131
159
  fingerprint: string;
132
160
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mneme-ai/xray",
3
- "version": "2.150.0",
3
+ "version": "2.151.0",
4
4
  "description": "Mneme Repo X-Ray — a signed, raw-free, deterministic X-Ray of any repo. Every number is reproducible from git/AST/metadata and sealed with an offline-verifiable NOTARY receipt. No source code ever leaves the machine; no LLM guesses anything.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/public/card.js CHANGED
@@ -4,6 +4,25 @@
4
4
  const gC = (x) => "g-" + ("ABCDEF".includes(x) ? x : "C");
5
5
  const pct = (n) => (n || 0) + "%";
6
6
 
7
+ // tiny unicode sparkline from an array of numbers
8
+ function sparkline(arr) {
9
+ if (!arr || !arr.length) return "";
10
+ const bars = "▁▂▃▄▅▆▇█", max = Math.max(1, ...arr);
11
+ return `<span class="spark" title="activity over time (oldest → newest)">${arr.map((n) => bars[Math.min(7, Math.round((n / max) * 7))]).join("")}</span>`;
12
+ }
13
+
14
+ // one-line "what is this / what's it for" under every label
15
+ const INFO = {
16
+ Dependencies: "Are your libraries dying or legally risky?",
17
+ Secrets: "Leaked credentials sitting in the code.",
18
+ "Bus factor": "Key-person risk — what breaks if someone leaves.",
19
+ Vitality: "Is the project alive and maintained?",
20
+ Complexity: "The biggest, most tangled code.",
21
+ Hotspots: "Where bugs hide — refactor these first.",
22
+ Coupling: "Files that secretly change together.",
23
+ };
24
+ const kcell = (label) => `<div class="k">${label}${INFO[label] ? `<span class="kdesc">${INFO[label]}</span>` : ""}</div>`;
25
+
7
26
  function xrayCardHTML(signed, opts) {
8
27
  opts = opts || {};
9
28
  const r = signed.report, s = r.summary;
@@ -16,8 +35,13 @@
16
35
  Object.entries(sec.byKind).slice(0, 8).map(([k, n]) => `<span class="chip bad">${esc(k)} ×${n}</span>`).join("");
17
36
  const fragile = (bf.fragileFiles || []).slice(0, 4).map((x) => `<span class="chip ${x.topAuthorShare >= 0.9 ? "warn" : ""}">${esc(x.file)} · ${Math.round(x.topAuthorShare * 100)}%</span>`).join("");
18
37
  const hot = (cx.hotspots || []).slice(0, 4).map((h) => `<span class="chip">${esc(h.symbol).slice(0, 40)} · ${h.bodyLines}L</span>`).join("");
19
- const hs = r.hotspots || { hotspots: [] };
20
- const hsChips = (hs.hotspots || []).slice(0, 5).map((h) => `<span class="chip">${esc(h.file)} · ${h.changes}× · ${h.loc}L</span>`).join("") || `<span class="chip">none</span>`;
38
+ const hs = r.hotspots || { hotspots: [], trend: [] };
39
+ const hsChips = (hs.hotspots || []).slice(0, 5).map((h) => `<span class="chip">${esc(h.file)} · ${h.changes}× · ${h.loc}L${h.expert ? ` · ${esc(h.expert)}` : ""}</span>`).join("") || `<span class="chip">none</span>`;
40
+ const cp = r.coupling || { pairs: [] };
41
+ const cpChips = (cp.pairs || []).slice(0, 5).map((p) => `<span class="chip ${p.hidden ? "warn" : ""}">${esc(p.a)} ⇄ ${esc(p.b)} · ${Math.round(p.confidence * 100)}%</span>`).join("") || `<span class="chip">none</span>`;
42
+ const lic = (dep.licenses) || { permissive: 0, "weak-copyleft": 0, "strong-copyleft": 0, unknown: 0 };
43
+ const licChips = (dep.licenseFlags || []).slice(0, 5).map((l) => `<span class="chip ${l.class === "strong-copyleft" ? "bad" : "warn"}">${esc(l.name)} · ${esc(l.license)}</span>`).join("");
44
+ const spark = sparkline(hs.trend || []);
21
45
 
22
46
  const share = opts.share ? `<div class="share" id="share"></div>` : "";
23
47
 
@@ -29,12 +53,13 @@
29
53
  <div class="head">${esc(s.headline)} · ${s.signalsRun} signals · @ ${esc(String(r.subject.commitHash).slice(0, 10))}</div></div>
30
54
  </div>
31
55
  <div class="rows">
32
- <div class="row"><div class="k">Dependencies</div><div class="v"><span class="big">${dep.total}</span> total · ${dep.byBand.dead + dep.byBand.moribund} dying<div class="chips">${depChips}</div></div></div>
33
- <div class="row"><div class="k">Secrets</div><div class="v"><span class="big">${sec.totalFindings}</span> in production code · ${sec.filesScanned} files${sec.excludedTestHits ? ` · <span class="muted">+${sec.excludedTestHits} in tests/docs (excluded)</span>` : ""}<div class="chips">${secChips}</div></div></div>
34
- <div class="row"><div class="k">Bus factor</div><div class="v"><span class="big">${bf.busFactor}</span> · top author ${pct(bf.topContributorShare)} · ${pct(bf.singleOwnerFilePct)} files single-owner<div class="chips">${fragile}</div></div></div>
35
- <div class="row"><div class="k">Vitality</div><div class="v"><span class="big">${esc(age.vitality)}</span> · ${esc(age.lifespan)} old · ${age.totalCommits} commits · ${age.totalAuthors} authors</div></div>
36
- <div class="row"><div class="k">Complexity</div><div class="v"><span class="big">${cx.totalSymbols}</span> symbols · ${cx.filesAnalysed} files · max depth ${cx.maxDepth}<div class="chips">${hot}</div></div></div>
37
- <div class="row"><div class="k">🔥 Hotspots</div><div class="v"><span class="muted">refactor-ROI · churn × size · last ${hs.windowDays||365}d</span><div class="chips">${hsChips}</div></div></div>
56
+ <div class="row">${kcell("Dependencies")}<div class="v"><span class="big">${dep.total}</span> total · ${dep.byBand.dead + dep.byBand.moribund} dying · ${(lic["strong-copyleft"] + lic["weak-copyleft"])} copyleft<div class="chips">${depChips}${licChips}</div></div></div>
57
+ <div class="row">${kcell("Secrets")}<div class="v"><span class="big">${sec.totalFindings}</span> in production code · ${sec.filesScanned} files${sec.excludedTestHits ? ` · <span class="muted">+${sec.excludedTestHits} in tests/docs (excluded)</span>` : ""}<div class="chips">${secChips}</div></div></div>
58
+ <div class="row">${kcell("Bus factor")}<div class="v"><span class="big">${bf.busFactor}</span> · top author ${pct(bf.topContributorShare)} · ${pct(bf.singleOwnerFilePct)} files single-owner<div class="chips">${fragile}</div></div></div>
59
+ <div class="row">${kcell("Vitality")}<div class="v"><span class="big">${esc(age.vitality)}</span> · ${esc(age.lifespan)} old · ${age.totalCommits} commits · ${age.totalAuthors} authors</div></div>
60
+ <div class="row">${kcell("Complexity")}<div class="v"><span class="big">${cx.totalSymbols}</span> symbols · ${cx.filesAnalysed} files · max depth ${cx.maxDepth}<div class="chips">${hot}</div></div></div>
61
+ <div class="row">${kcell("Hotspots")}<div class="v"><span class="muted">refactor-ROI · churn × size · last ${hs.windowDays||365}d</span> ${spark}<div class="chips">${hsChips}</div></div></div>
62
+ <div class="row">${kcell("Coupling")}<div class="v"><span class="muted">${(cp.pairs||[]).length} coupled pair(s) · hidden = cross-directory</span><div class="chips">${cpChips}</div></div></div>
38
63
  </div>
39
64
  <div class="foot">${verified}<span>fingerprint <code>${esc(String(r.fingerprint).slice(0, 28))}…</code></span></div>
40
65
  ${share}
package/public/index.html CHANGED
@@ -109,7 +109,18 @@
109
109
  .muted{color:var(--sub)}
110
110
  /* crisper section separation */
111
111
  .card .top{background:linear-gradient(#fff,#fcfcfd)}
112
- .row .k{font-weight:560}
112
+ .row .k{font-weight:560;display:flex;flex-direction:column;gap:3px}
113
+ .kdesc{font-size:11px;color:var(--sub);text-transform:none;letter-spacing:0;font-weight:400;line-height:1.3}
114
+ .spark{font-family:ui-monospace,Menlo,monospace;letter-spacing:1px;color:var(--a)}
115
+ /* local-folder bridge panel */
116
+ .localbox{max-width:560px;margin:18px auto 0;border:1px solid var(--line);border-radius:14px;padding:16px 18px;background:var(--soft);display:none}
117
+ .localbox.on{display:block}
118
+ .localbox .lh{display:flex;align-items:center;gap:8px;font-size:13.5px;font-weight:560}
119
+ .localdot{width:8px;height:8px;border-radius:50%;background:var(--green)}
120
+ .localrow{display:flex;gap:8px;margin-top:10px}
121
+ .localrow input{flex:1;padding:11px 13px;border:1px solid var(--line);border-radius:10px;font-size:14px;font-family:ui-monospace,Menlo,monospace}
122
+ .localrow button{padding:11px 16px;border:0;border-radius:10px;background:var(--ink);color:#fff;cursor:pointer;font-size:14px}
123
+ .localhint{font-size:12px;color:var(--sub);margin-top:8px}
113
124
  /* ---- mobile / cross-browser responsive ---- */
114
125
  @media (max-width:680px){
115
126
  .wrap{padding:0 16px}
@@ -156,6 +167,14 @@
156
167
  <span id="keystate" class="kstate"></span>
157
168
  </div>
158
169
  </details>
170
+ <div class="localbox" id="localbox">
171
+ <div class="lh"><span class="localdot"></span>Local agent detected — scan a folder on <b>this machine</b> (source never leaves it)</div>
172
+ <div class="localrow">
173
+ <input id="localpath" placeholder="/absolute/path/to/your/repo (git or not)" autocomplete="off" spellcheck="false" />
174
+ <button id="localgo" type="button">Scan local</button>
175
+ </div>
176
+ <div class="localhint">Private code? This reads it locally and shows the signed result here — nothing is uploaded.</div>
177
+ </div>
159
178
  <p class="err" id="err" style="display:none"></p>
160
179
  </header>
161
180
 
@@ -287,6 +306,30 @@ document.getElementById("f").addEventListener("submit", async e=>{
287
306
  }catch(ex){ err.textContent = String(ex); err.style.display="block"; }
288
307
  finally{ go.disabled=false; go.textContent="X-Ray"; }
289
308
  });
309
+ // ---- LOCAL BRIDGE: detect the local agent + scan a folder (code never uploaded) ----
310
+ const BRIDGE = "http://127.0.0.1:7799";
311
+ async function detectBridge(){
312
+ try{
313
+ const ctrl=new AbortController(); const t=setTimeout(()=>ctrl.abort(),1200);
314
+ const r=await fetch(BRIDGE+"/bridge/ping",{signal:ctrl.signal}); clearTimeout(t);
315
+ if(r.ok){ document.getElementById("localbox").classList.add("on"); }
316
+ }catch{ /* no local agent — silent */ }
317
+ }
318
+ document.getElementById("localgo").addEventListener("click", async ()=>{
319
+ const p=document.getElementById("localpath").value.trim();
320
+ const err=document.getElementById("err"), btn=document.getElementById("localgo");
321
+ err.style.display="none"; document.getElementById("out").innerHTML="";
322
+ if(!p) return;
323
+ btn.disabled=true; btn.innerHTML='<span class="spin"></span>Scanning…';
324
+ try{
325
+ const res=await fetch(BRIDGE+"/bridge/xray",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({path:p})});
326
+ const data=await res.json();
327
+ if(!res.ok){ err.textContent=data.error||"local scan failed"; err.style.display="block"; }
328
+ else { render(data); window.scrollTo({top:0,behavior:"smooth"}); }
329
+ }catch(ex){ err.textContent="Could not reach the local agent. Run: npx @mneme-ai/xray bridge"; err.style.display="block"; }
330
+ finally{ btn.disabled=false; btn.textContent="Scan local"; }
331
+ });
332
+ detectBridge();
290
333
  refreshKeyState();
291
334
  loadList();
292
335
  </script>
@@ -21,7 +21,11 @@
21
21
  .top .repo{font-size:21px;font-weight:620;word-break:break-all}.top .head{color:var(--sub);font-size:14.5px;margin-top:2px}
22
22
  .rows{padding:8px 28px 14px}
23
23
  .row{display:flex;gap:14px;padding:15px 0;border-bottom:1px solid var(--soft);align-items:baseline}.row:last-child{border-bottom:0}
24
- .row .k{font-size:13px;letter-spacing:.04em;text-transform:uppercase;color:var(--sub);width:128px;flex:none}
24
+ .row .k{font-size:13px;letter-spacing:.04em;text-transform:uppercase;color:var(--sub);width:140px;flex:none;display:flex;flex-direction:column;gap:3px}
25
+ .kdesc{font-size:11px;color:var(--sub);text-transform:none;letter-spacing:0;line-height:1.3}
26
+ .spark{font-family:ui-monospace,Menlo,monospace;letter-spacing:1px;color:#4f46e5}
27
+ .muted{color:var(--sub)}
28
+ @media (max-width:640px){ .row{flex-direction:column;gap:4px} .row .k{width:auto} }
25
29
  .row .v{font-size:15.5px}.row .v .big{font-weight:640}
26
30
  .chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
27
31
  .chip{font-size:12.5px;padding:3px 9px;border-radius:999px;background:var(--soft);border:1px solid var(--line);color:#374151}