@nanonets/graft 0.10.0 → 0.12.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 (238) hide show
  1. package/README.md +34 -13
  2. package/dist/ai/crux.d.ts.map +1 -1
  3. package/dist/ai/crux.js +7 -6
  4. package/dist/ai/crux.js.map +1 -1
  5. package/dist/ai/failure.d.ts +49 -0
  6. package/dist/ai/failure.d.ts.map +1 -0
  7. package/dist/ai/failure.js +74 -0
  8. package/dist/ai/failure.js.map +1 -0
  9. package/dist/ai/llm/anthropic.d.ts.map +1 -1
  10. package/dist/ai/llm/anthropic.js +4 -1
  11. package/dist/ai/llm/anthropic.js.map +1 -1
  12. package/dist/ai/llm/claude-cli.d.ts +60 -0
  13. package/dist/ai/llm/claude-cli.d.ts.map +1 -0
  14. package/dist/ai/llm/claude-cli.js +417 -0
  15. package/dist/ai/llm/claude-cli.js.map +1 -0
  16. package/dist/ai/llm/openai.d.ts.map +1 -1
  17. package/dist/ai/llm/openai.js +2 -0
  18. package/dist/ai/llm/openai.js.map +1 -1
  19. package/dist/ai/llm/types.d.ts +9 -0
  20. package/dist/ai/llm/types.d.ts.map +1 -1
  21. package/dist/ai/llm/types.js +12 -1
  22. package/dist/ai/llm/types.js.map +1 -1
  23. package/dist/ask/ask.d.ts.map +1 -1
  24. package/dist/ask/ask.js +39 -45
  25. package/dist/ask/ask.js.map +1 -1
  26. package/dist/ask/fuse.d.ts +83 -46
  27. package/dist/ask/fuse.d.ts.map +1 -1
  28. package/dist/ask/fuse.js +165 -67
  29. package/dist/ask/fuse.js.map +1 -1
  30. package/dist/blast/blast-cli.d.ts +30 -0
  31. package/dist/blast/blast-cli.d.ts.map +1 -0
  32. package/dist/blast/blast-cli.js +163 -0
  33. package/dist/blast/blast-cli.js.map +1 -0
  34. package/dist/blast/blast.d.ts +119 -0
  35. package/dist/blast/blast.d.ts.map +1 -0
  36. package/dist/blast/blast.js +383 -0
  37. package/dist/blast/blast.js.map +1 -0
  38. package/dist/blast/diff.d.ts +53 -0
  39. package/dist/blast/diff.d.ts.map +1 -0
  40. package/dist/blast/diff.js +193 -0
  41. package/dist/blast/diff.js.map +1 -0
  42. package/dist/blast/modules.d.ts +33 -0
  43. package/dist/blast/modules.d.ts.map +1 -0
  44. package/dist/blast/modules.js +83 -0
  45. package/dist/blast/modules.js.map +1 -0
  46. package/dist/blast/name.d.ts +61 -0
  47. package/dist/blast/name.d.ts.map +1 -0
  48. package/dist/blast/name.js +233 -0
  49. package/dist/blast/name.js.map +1 -0
  50. package/dist/blast/render.d.ts +37 -0
  51. package/dist/blast/render.d.ts.map +1 -0
  52. package/dist/blast/render.js +300 -0
  53. package/dist/blast/render.js.map +1 -0
  54. package/dist/blast/viz.d.ts +17 -0
  55. package/dist/blast/viz.d.ts.map +1 -0
  56. package/dist/blast/viz.js +324 -0
  57. package/dist/blast/viz.js.map +1 -0
  58. package/dist/claude/hooks.d.ts +13 -0
  59. package/dist/claude/hooks.d.ts.map +1 -1
  60. package/dist/claude/hooks.js +44 -4
  61. package/dist/claude/hooks.js.map +1 -1
  62. package/dist/claude/shim-template.d.ts.map +1 -1
  63. package/dist/claude/shim-template.js +45 -15
  64. package/dist/claude/shim-template.js.map +1 -1
  65. package/dist/claude/state.d.ts +5 -0
  66. package/dist/claude/state.d.ts.map +1 -1
  67. package/dist/claude/state.js.map +1 -1
  68. package/dist/cli-picker.d.ts +44 -5
  69. package/dist/cli-picker.d.ts.map +1 -1
  70. package/dist/cli-picker.js +73 -26
  71. package/dist/cli-picker.js.map +1 -1
  72. package/dist/cli.js +270 -14
  73. package/dist/cli.js.map +1 -1
  74. package/dist/context/build.d.ts +8 -0
  75. package/dist/context/build.d.ts.map +1 -1
  76. package/dist/context/build.js +57 -9
  77. package/dist/context/build.js.map +1 -1
  78. package/dist/context/check.d.ts.map +1 -1
  79. package/dist/context/check.js +7 -6
  80. package/dist/context/check.js.map +1 -1
  81. package/dist/context/node-file.d.ts.map +1 -1
  82. package/dist/context/node-file.js +9 -2
  83. package/dist/context/node-file.js.map +1 -1
  84. package/dist/graph/bindings.d.ts.map +1 -1
  85. package/dist/graph/bindings.js +245 -2
  86. package/dist/graph/bindings.js.map +1 -1
  87. package/dist/graph/build.d.ts.map +1 -1
  88. package/dist/graph/build.js +36 -16
  89. package/dist/graph/build.js.map +1 -1
  90. package/dist/graph/check.d.ts +4 -0
  91. package/dist/graph/check.d.ts.map +1 -1
  92. package/dist/graph/check.js +8 -1
  93. package/dist/graph/check.js.map +1 -1
  94. package/dist/graph/container.d.ts +63 -0
  95. package/dist/graph/container.d.ts.map +1 -0
  96. package/dist/graph/container.js +185 -0
  97. package/dist/graph/container.js.map +1 -0
  98. package/dist/graph/enrich.d.ts +18 -0
  99. package/dist/graph/enrich.d.ts.map +1 -1
  100. package/dist/graph/enrich.js +55 -2
  101. package/dist/graph/enrich.js.map +1 -1
  102. package/dist/graph/extract.d.ts +8 -1
  103. package/dist/graph/extract.d.ts.map +1 -1
  104. package/dist/graph/extract.js +401 -12
  105. package/dist/graph/extract.js.map +1 -1
  106. package/dist/graph/generic.d.ts +34 -1
  107. package/dist/graph/generic.d.ts.map +1 -1
  108. package/dist/graph/generic.js +176 -6
  109. package/dist/graph/generic.js.map +1 -1
  110. package/dist/graph/invariants.d.ts +32 -0
  111. package/dist/graph/invariants.d.ts.map +1 -0
  112. package/dist/graph/invariants.js +49 -0
  113. package/dist/graph/invariants.js.map +1 -0
  114. package/dist/graph/queries/clojure.scm +58 -0
  115. package/dist/graph/resolve.d.ts.map +1 -1
  116. package/dist/graph/resolve.js +249 -23
  117. package/dist/graph/resolve.js.map +1 -1
  118. package/dist/graph/scopes.d.ts +2 -2
  119. package/dist/graph/scopes.d.ts.map +1 -1
  120. package/dist/graph/scopes.js +8 -6
  121. package/dist/graph/scopes.js.map +1 -1
  122. package/dist/graph/source-files.d.ts +13 -4
  123. package/dist/graph/source-files.d.ts.map +1 -1
  124. package/dist/graph/source-files.js +35 -12
  125. package/dist/graph/source-files.js.map +1 -1
  126. package/dist/graph/types.d.ts +3 -1
  127. package/dist/graph/types.d.ts.map +1 -1
  128. package/dist/graph/workspace-cli.d.ts +2 -0
  129. package/dist/graph/workspace-cli.d.ts.map +1 -1
  130. package/dist/graph/workspace-cli.js +10 -4
  131. package/dist/graph/workspace-cli.js.map +1 -1
  132. package/dist/graph/workspace.d.ts +11 -6
  133. package/dist/graph/workspace.d.ts.map +1 -1
  134. package/dist/graph/workspace.js +24 -13
  135. package/dist/graph/workspace.js.map +1 -1
  136. package/dist/graph/write.d.ts.map +1 -1
  137. package/dist/graph/write.js +25 -2
  138. package/dist/graph/write.js.map +1 -1
  139. package/dist/hosts/antigravity.d.ts +7 -0
  140. package/dist/hosts/antigravity.d.ts.map +1 -0
  141. package/dist/hosts/antigravity.js +42 -0
  142. package/dist/hosts/antigravity.js.map +1 -0
  143. package/dist/hosts/codex-hooks.d.ts +3 -3
  144. package/dist/hosts/codex-hooks.d.ts.map +1 -1
  145. package/dist/hosts/codex-hooks.js +27 -21
  146. package/dist/hosts/codex-hooks.js.map +1 -1
  147. package/dist/hosts/init.d.ts.map +1 -1
  148. package/dist/hosts/init.js +6 -1
  149. package/dist/hosts/init.js.map +1 -1
  150. package/dist/hosts/mcp-config.d.ts.map +1 -1
  151. package/dist/hosts/mcp-config.js +7 -0
  152. package/dist/hosts/mcp-config.js.map +1 -1
  153. package/dist/hosts/plan.d.ts +1 -1
  154. package/dist/hosts/plan.d.ts.map +1 -1
  155. package/dist/hosts/plan.js +2 -0
  156. package/dist/hosts/plan.js.map +1 -1
  157. package/dist/hosts/registry.d.ts.map +1 -1
  158. package/dist/hosts/registry.js +13 -0
  159. package/dist/hosts/registry.js.map +1 -1
  160. package/dist/ingest/fs.d.ts +9 -2
  161. package/dist/ingest/fs.d.ts.map +1 -1
  162. package/dist/ingest/fs.js +100 -16
  163. package/dist/ingest/fs.js.map +1 -1
  164. package/dist/mcp/server.d.ts.map +1 -1
  165. package/dist/mcp/server.js +45 -2
  166. package/dist/mcp/server.js.map +1 -1
  167. package/dist/telemetry/contract.d.ts +90 -0
  168. package/dist/telemetry/contract.d.ts.map +1 -0
  169. package/dist/telemetry/contract.js +203 -0
  170. package/dist/telemetry/contract.js.map +1 -0
  171. package/dist/telemetry/flush.d.ts +21 -0
  172. package/dist/telemetry/flush.d.ts.map +1 -0
  173. package/dist/telemetry/flush.js +84 -0
  174. package/dist/telemetry/flush.js.map +1 -0
  175. package/dist/telemetry/gate.d.ts +16 -0
  176. package/dist/telemetry/gate.d.ts.map +1 -0
  177. package/dist/telemetry/gate.js +64 -0
  178. package/dist/telemetry/gate.js.map +1 -0
  179. package/dist/telemetry/identity.d.ts +33 -0
  180. package/dist/telemetry/identity.d.ts.map +1 -0
  181. package/dist/telemetry/identity.js +80 -0
  182. package/dist/telemetry/identity.js.map +1 -0
  183. package/dist/telemetry/index.d.ts +18 -0
  184. package/dist/telemetry/index.d.ts.map +1 -0
  185. package/dist/telemetry/index.js +16 -0
  186. package/dist/telemetry/index.js.map +1 -0
  187. package/dist/telemetry/key.d.ts +21 -0
  188. package/dist/telemetry/key.d.ts.map +1 -0
  189. package/dist/telemetry/key.js +49 -0
  190. package/dist/telemetry/key.js.map +1 -0
  191. package/dist/telemetry/notice.d.ts +19 -0
  192. package/dist/telemetry/notice.d.ts.map +1 -0
  193. package/dist/telemetry/notice.js +90 -0
  194. package/dist/telemetry/notice.js.map +1 -0
  195. package/dist/telemetry/queue.d.ts +35 -0
  196. package/dist/telemetry/queue.d.ts.map +1 -0
  197. package/dist/telemetry/queue.js +162 -0
  198. package/dist/telemetry/queue.js.map +1 -0
  199. package/dist/telemetry/send.d.ts +19 -0
  200. package/dist/telemetry/send.d.ts.map +1 -0
  201. package/dist/telemetry/send.js +84 -0
  202. package/dist/telemetry/send.js.map +1 -0
  203. package/dist/telemetry/sessions.d.ts +8 -0
  204. package/dist/telemetry/sessions.d.ts.map +1 -0
  205. package/dist/telemetry/sessions.js +81 -0
  206. package/dist/telemetry/sessions.js.map +1 -0
  207. package/dist/telemetry/track.d.ts +43 -0
  208. package/dist/telemetry/track.d.ts.map +1 -0
  209. package/dist/telemetry/track.js +108 -0
  210. package/dist/telemetry/track.js.map +1 -0
  211. package/dist/upkeep-run.d.ts +15 -0
  212. package/dist/upkeep-run.d.ts.map +1 -0
  213. package/dist/upkeep-run.js +60 -0
  214. package/dist/upkeep-run.js.map +1 -0
  215. package/dist/upkeep.d.ts +114 -0
  216. package/dist/upkeep.d.ts.map +1 -0
  217. package/dist/upkeep.js +232 -0
  218. package/dist/upkeep.js.map +1 -0
  219. package/dist/util/num.d.ts +3 -0
  220. package/dist/util/num.d.ts.map +1 -0
  221. package/dist/util/num.js +20 -0
  222. package/dist/util/num.js.map +1 -0
  223. package/dist/util/state.d.ts +11 -4
  224. package/dist/util/state.d.ts.map +1 -1
  225. package/dist/util/state.js +9 -0
  226. package/dist/util/state.js.map +1 -1
  227. package/dist/viewer/app.js +1 -1
  228. package/dist/viewer/index.html +1 -0
  229. package/dist/viewer/style.css +23 -2
  230. package/dist/viz/assemble.d.ts +33 -0
  231. package/dist/viz/assemble.d.ts.map +1 -1
  232. package/dist/viz/assemble.js.map +1 -1
  233. package/dist/viz/export.d.ts +39 -0
  234. package/dist/viz/export.d.ts.map +1 -0
  235. package/dist/viz/export.js +98 -0
  236. package/dist/viz/export.js.map +1 -0
  237. package/package.json +15 -5
  238. package/scripts/stamp-telemetry-key.mjs +53 -0
@@ -0,0 +1,119 @@
1
+ import type { GraphV1 } from "../graph/types.js";
2
+ import { type ModuleIndex } from "./modules.js";
3
+ import type { ChangedFile } from "./diff.js";
4
+ export interface BlastOptions {
5
+ /** BFS depth over incoming edges; `Infinity` for the full closure. */
6
+ depth: number;
7
+ /** Concept/directory labels. Built from the context dir when omitted. */
8
+ modules?: ModuleIndex;
9
+ }
10
+ /** A changed symbol the walk started from. */
11
+ export interface Seed {
12
+ id: string;
13
+ name: string;
14
+ kind: string;
15
+ path: string;
16
+ span: string;
17
+ /** True for a whole-file seed (an added file, or a change outside any symbol). */
18
+ wholeFile: boolean;
19
+ }
20
+ /** One dependent symbol, and how the walk reached it. */
21
+ export interface Impacted {
22
+ id: string;
23
+ name: string;
24
+ kind: string;
25
+ path: string;
26
+ span: string;
27
+ relation: string;
28
+ depth: number;
29
+ }
30
+ /**
31
+ * Where a cluster's label came from — the rungs of the naming ladder.
32
+ *
33
+ * `concept` — a concept node from a `--deep` build claims every file in the cluster.
34
+ * `named` — `graft blast --name` asked a model to name this cluster (see name.ts).
35
+ * `symbol` — the deterministic backstop: the cluster's most significant symbol.
36
+ *
37
+ * A bare directory is never a label. The whole point of the picture is that a
38
+ * reviewer reads what is affected, and `src/graph/` tells them nothing they could
39
+ * not get from the diff — but it must never be replaced by a guess either, so the
40
+ * backstop names a real symbol rather than inventing a feature name.
41
+ */
42
+ export type LabelSource = "concept" | "named" | "symbol";
43
+ /** Dependents grouped for the diagram: the unit a reviewer actually thinks in. */
44
+ export interface ImpactedModule {
45
+ label: string;
46
+ labelSource: LabelSource;
47
+ /** Stable identity for the cluster, independent of its label: the concept name
48
+ * or the directory it was grouped by. Naming and its cache key hang off this. */
49
+ key: string;
50
+ files: string[];
51
+ symbols: Impacted[];
52
+ /** Changed files whose edges reached this module — the diagram's arrows. */
53
+ from: string[];
54
+ }
55
+ /**
56
+ * Whether the diff brought its tests along.
57
+ *
58
+ * `changed` — a test file that reaches this area was edited in this PR.
59
+ * `stale` — tests reach it and the diff left every one of them alone.
60
+ * `none` — nothing under `test/` reaches it at all.
61
+ * `na` — no function, method or class changed here, so there is nothing to
62
+ * ask the question of: a types-only file, or config and wiring.
63
+ */
64
+ export type TestSignal = "changed" | "stale" | "none" | "na";
65
+ /** One area of the diff: the changed files a reviewer thinks of as one thing. */
66
+ export interface ChangedArea {
67
+ label: string;
68
+ labelSource: LabelSource;
69
+ /** The directory the cluster was grouped by — see {@link ImpactedModule.key}. */
70
+ key: string;
71
+ /** Changed, indexed, non-test files grouped under this label. */
72
+ files: string[];
73
+ /** Changed symbols seeded from those files. */
74
+ seeds: number;
75
+ tests: TestSignal;
76
+ /** Test files with an edge into this area, and those of them the diff changed. */
77
+ testFiles: string[];
78
+ changedTestFiles: string[];
79
+ /** Test reach, over the area's exported functions/methods/classes only. */
80
+ reached: number;
81
+ behavioural: number;
82
+ /** Names of the behavioural symbols no test reaches, for the collapsed detail. */
83
+ unreached: string[];
84
+ /** Changed symbol names, behaviour first — the backstop label and the naming
85
+ * prompt both read from this. */
86
+ seedNames: string[];
87
+ }
88
+ export interface BlastReport {
89
+ basis: string;
90
+ depth: number;
91
+ changed: ChangedFile[];
92
+ /** Changed paths the graph has no node for: unsupported language, or deleted. */
93
+ unindexed: string[];
94
+ /** Changed paths that were deleted, called out because their dependents are
95
+ * unknowable from a graph built at the post-change commit. */
96
+ deleted: string[];
97
+ seeds: Seed[];
98
+ impacted: Impacted[];
99
+ modules: ImpactedModule[];
100
+ /** The diff itself, grouped: the left-hand side of the diagram. */
101
+ areas: ChangedArea[];
102
+ /** Test-only dependents, kept out of `modules` so they cannot crowd it out. */
103
+ testModules: ImpactedModule[];
104
+ }
105
+ /** Compute the blast radius of `changed` against `graph`. */
106
+ export declare function blastRadius(graph: GraphV1, changed: ChangedFile[], basis: string, opts: BlastOptions): BlastReport;
107
+ /** Convenience wrapper: build the module index from a context dir. */
108
+ export declare function blastRadiusIn(graph: GraphV1, contextDir: string, changed: ChangedFile[], basis: string, depth: number): BlastReport;
109
+ /**
110
+ * The deterministic backstop label: the cluster's most significant symbol.
111
+ *
112
+ * Reached with no concept, no cache and no API key, so this is what guarantees a
113
+ * circle never carries a bare directory. It is a fact rather than a guess — the
114
+ * reviewer can grep the name — which is why it beats borrowing a neighbouring
115
+ * concept: on graft's own graph that borrowing labelled the freshness gate
116
+ * "Graph Extraction and Loading", which misleads worse than any path.
117
+ */
118
+ export declare function hubLabel(names: string[], fallback: string): string;
119
+ //# sourceMappingURL=blast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blast.d.ts","sourceRoot":"","sources":["../../src/blast/blast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,383 @@
1
+ /**
2
+ * Blast radius of a diff: what else in the repo depends on the lines this change
3
+ * touched.
4
+ *
5
+ * The whole command is a join between two things graft already has — git's changed
6
+ * line ranges (`diff.ts`) and the wiring graph's incoming edges (`traverse.ts`) —
7
+ * so there is no new graph logic here, only the seeding rule:
8
+ *
9
+ * changed line → the innermost symbol whose span contains it → seed
10
+ *
11
+ * Seeding by SYMBOL rather than by file is what makes the answer worth reading: a
12
+ * 400-line file with a one-line edit reports the dependents of that one function,
13
+ * not of everything the file happens to define. The file node is seeded too, so
14
+ * importers (whose edge targets the file, not the symbol) are still found.
15
+ */
16
+ import { impactOfMany } from "../graph/traverse.js";
17
+ import { dirLabel, moduleIndex, parentDir, shortLabel } from "./modules.js";
18
+ const SPAN_RE = /^L(\d+)-L(\d+)$/;
19
+ function spanBounds(span) {
20
+ const m = SPAN_RE.exec(span);
21
+ return m ? { start: Number(m[1]), end: Number(m[2]) } : null;
22
+ }
23
+ /**
24
+ * The innermost symbols whose spans overlap any changed range in `path`.
25
+ *
26
+ * "Innermost" matters for a method: a changed line inside `Cache.get` overlaps both
27
+ * the class span and the method span, and seeding the class would report everyone
28
+ * who touches any part of `Cache`. Nesting is resolved by keeping, for each range,
29
+ * only symbols that contain no other matched symbol.
30
+ */
31
+ function seedsForFile(graph, path, ranges) {
32
+ const symbols = [];
33
+ for (const n of graph.nodes) {
34
+ if (n.kind === "file" || n.path !== path)
35
+ continue;
36
+ const b = spanBounds(n.span);
37
+ if (b)
38
+ symbols.push({ node: n, ...b });
39
+ }
40
+ if (symbols.length === 0)
41
+ return [];
42
+ const hit = new Map();
43
+ for (const r of ranges) {
44
+ const overlapping = symbols.filter((s) => s.start <= r.end && s.end >= r.start);
45
+ // Drop any symbol that strictly contains another overlapping one (the class
46
+ // around a changed method), keeping the tightest description of the edit.
47
+ for (const s of overlapping) {
48
+ const containsAnother = overlapping.some((o) => o !== s && o.start >= s.start && o.end <= s.end);
49
+ if (!containsAnother)
50
+ hit.set(s.node.id, s.node);
51
+ }
52
+ }
53
+ return [...hit.values()];
54
+ }
55
+ /** Compute the blast radius of `changed` against `graph`. */
56
+ export function blastRadius(graph, changed, basis, opts) {
57
+ const fileNodes = new Map();
58
+ for (const n of graph.nodes)
59
+ if (n.kind === "file")
60
+ fileNodes.set(n.path, n);
61
+ const seeds = [];
62
+ const unindexed = [];
63
+ const deleted = [];
64
+ /** Seed nodes per changed file, kept for the area grouping and the test signal. */
65
+ const seedNodes = new Map();
66
+ /** Merged dependents, keyed by node id, at the shallowest depth any file reached
67
+ * them — plus which changed files did the reaching. */
68
+ const merged = new Map();
69
+ for (const file of changed) {
70
+ if (file.status === "deleted") {
71
+ deleted.push(file.path);
72
+ continue;
73
+ }
74
+ const fileNode = fileNodes.get(file.path);
75
+ if (!fileNode) {
76
+ unindexed.push(file.path);
77
+ continue;
78
+ }
79
+ // No hunk ranges (a rename with no content change, a mode change) or an added
80
+ // file: the unit of change is the file itself.
81
+ const symbolSeeds = file.ranges.length > 0 ? seedsForFile(graph, file.path, file.ranges) : [];
82
+ for (const node of symbolSeeds) {
83
+ seeds.push({ id: node.id, name: node.name, kind: node.kind, path: node.path, span: node.span, wholeFile: false });
84
+ }
85
+ if (symbolSeeds.length === 0) {
86
+ seeds.push({
87
+ id: fileNode.id, name: fileNode.name, kind: fileNode.kind,
88
+ path: fileNode.path, span: fileNode.span, wholeFile: true,
89
+ });
90
+ }
91
+ // One walk PER CHANGED FILE, not one walk over every seed at once. A combined
92
+ // walk records the depth a node was first reached at but not by which seed, so
93
+ // the diagram could only draw "every changed file reaches every module" — a
94
+ // cross-product that tells a reviewer nothing. Walking per file costs one
95
+ // adjacency build each (cheap: the graph is already in memory) and buys arrows
96
+ // that are true.
97
+ //
98
+ // The FILE node is a seed only when no symbol matched. `imports` edges target
99
+ // the file id, so seeding it alongside symbols would pull in every importer of
100
+ // the file — a one-line edit to one function would report every module that
101
+ // imports the module, which is the noise this command exists to avoid. With no
102
+ // symbol seeds (a change to a top-level constant, a new import, a file with no
103
+ // extracted symbols) the file IS the unit of change, and its importers are the
104
+ // only dependents there are.
105
+ const walkSeeds = symbolSeeds.length > 0 ? symbolSeeds : [fileNode];
106
+ seedNodes.set(file.path, walkSeeds);
107
+ const hits = impactOfMany(graph, walkSeeds, opts.depth, "in");
108
+ for (const h of hits) {
109
+ if (!hasNode(h))
110
+ continue;
111
+ const hit = toImpacted(h);
112
+ const prev = merged.get(hit.id);
113
+ if (!prev)
114
+ merged.set(hit.id, { hit, from: new Set([file.path]) });
115
+ else {
116
+ prev.from.add(file.path);
117
+ // Keep the shallowest reach: a symbol two hops from one changed file and one
118
+ // hop from another is one hop away from this PR.
119
+ if (hit.depth < prev.hit.depth)
120
+ prev.hit = hit;
121
+ }
122
+ }
123
+ }
124
+ const impacted = [...merged.values()].map((m) => m.hit);
125
+ const origins = new Map([...merged].map(([id, m]) => [id, m.from]));
126
+ const index = opts.modules ?? emptyIndex();
127
+ const grouped = groupByModule(impacted, changed, origins, index);
128
+ return {
129
+ basis,
130
+ depth: opts.depth,
131
+ changed,
132
+ unindexed,
133
+ deleted,
134
+ seeds,
135
+ impacted,
136
+ modules: grouped.modules,
137
+ testModules: grouped.testModules,
138
+ areas: changedAreas(graph, changed, seedNodes, index, grouped.modules),
139
+ };
140
+ }
141
+ /**
142
+ * Group the changed files into areas, and work out whether each one's tests moved.
143
+ *
144
+ * The diff's own side of the diagram used to be one box per changed file, which can
145
+ * never fit: a 24-file PR drew ten arbitrary paths. Grouped by the same concept
146
+ * labels the dependents use, the same PR is three or four circles — and once the
147
+ * files are grouped, "did a test that reaches this move too?" is one question per
148
+ * circle instead of per file.
149
+ */
150
+ function changedAreas(graph, changed, seedNodes, index, modules) {
151
+ const changedTests = new Set(changed.filter((c) => TEST_PATH.test(c.path)).map((c) => c.path));
152
+ const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
153
+ /** How many edges point AT each node — how central it is in the graph. */
154
+ const inDegree = new Map();
155
+ for (const e of graph.edges)
156
+ inDegree.set(e.target, (inDegree.get(e.target) ?? 0) + 1);
157
+ /** Incoming edge sources per node id, resolved to the source's file path. */
158
+ const incoming = new Map();
159
+ for (const e of graph.edges) {
160
+ const path = nodeById.get(e.source)?.path;
161
+ if (!path || !TEST_PATH.test(path))
162
+ continue;
163
+ const at = incoming.get(e.target) ?? new Set();
164
+ at.add(path);
165
+ incoming.set(e.target, at);
166
+ }
167
+ // Group by DIRECTORY, not by concept. Concepts in a well-summarised repo are
168
+ // near-file-grained — graft's own PR produced nine of them, one file each — so
169
+ // grouping the diff by concept groups nothing: the left side was nine circles
170
+ // with near-identical truncated names. A directory is the coarser unit reviewers
171
+ // already use, and a concept name is only worth borrowing when one concept
172
+ // happens to claim the whole group.
173
+ const groups = new Map();
174
+ for (const path of seedNodes.keys()) {
175
+ // A changed test file is the signal, not the source of a blast radius. Drawing
176
+ // it as an area would put "your tests changed" on both sides of the arrow.
177
+ if (TEST_PATH.test(path))
178
+ continue;
179
+ const dir = dirLabel(path);
180
+ groups.set(dir, [...(groups.get(dir) ?? []), path]);
181
+ }
182
+ coarsen(groups, MAX_AREAS);
183
+ const byKey = new Map();
184
+ /** Hub candidates per area, ranked once every seed has been seen. */
185
+ const candidates = new Map();
186
+ for (const [dir, paths] of groups) {
187
+ const area = {
188
+ label: dir, labelSource: "symbol", key: dir,
189
+ files: [], seeds: 0, tests: "none", testFiles: [], changedTestFiles: [],
190
+ reached: 0, behavioural: 0, unreached: [], seedNames: [],
191
+ };
192
+ byKey.set(dir, area);
193
+ for (const path of paths) {
194
+ const nodes = seedNodes.get(path) ?? [];
195
+ area.files.push(path);
196
+ area.seeds += nodes.length;
197
+ for (const node of nodes) {
198
+ // Reach is measured over behaviour only. Counting interfaces and type aliases
199
+ // would sink every ratio: nothing "calls" a type, so a fully tested area of
200
+ // typed code would report a third of its symbols as unreached.
201
+ const behavioural = node.kind === "function" || node.kind === "method" || node.kind === "class";
202
+ const from = incoming.get(node.id) ?? new Set();
203
+ for (const t of from) {
204
+ if (!area.testFiles.includes(t))
205
+ area.testFiles.push(t);
206
+ if (changedTests.has(t) && !area.changedTestFiles.includes(t))
207
+ area.changedTestFiles.push(t);
208
+ }
209
+ candidates.set(area, [
210
+ ...(candidates.get(area) ?? []),
211
+ { name: node.name, behavioural, degree: inDegree.get(node.id) ?? 0 },
212
+ ]);
213
+ if (!behavioural)
214
+ continue;
215
+ area.behavioural++;
216
+ if (from.size > 0)
217
+ area.reached++;
218
+ else
219
+ area.unreached.push(node.name);
220
+ }
221
+ }
222
+ }
223
+ for (const area of byKey.values()) {
224
+ // The hub is the most-depended-on function in the area, not whichever symbol the
225
+ // file walk happened to end on: `LlmFailureGate` rather than `transportRetries`.
226
+ // Behaviour outranks types, since nothing calls an interface.
227
+ area.seedNames = (candidates.get(area) ?? [])
228
+ .sort((a, b) => Number(b.behavioural) - Number(a.behavioural) || b.degree - a.degree || a.name.localeCompare(b.name))
229
+ .map((c) => c.name);
230
+ const concept = sharedConcept(area.files, index);
231
+ area.label = concept ?? hubLabel(area.seedNames, area.key);
232
+ area.labelSource = concept ? "concept" : "symbol";
233
+ area.files.sort();
234
+ area.testFiles.sort();
235
+ area.changedTestFiles.sort();
236
+ area.tests =
237
+ area.behavioural === 0 ? "na"
238
+ : area.changedTestFiles.length > 0 ? "changed"
239
+ : area.testFiles.length > 0 ? "stale"
240
+ : "none";
241
+ }
242
+ // Ordered by how much each area actually reaches, because the diagram caps this
243
+ // list and folds the rest into one circle. Ordered by size instead, the fold ends
244
+ // up holding the best-connected areas and the tail circle collects every arrow —
245
+ // the same mistake, one level up, as capping changed FILES in diff order.
246
+ const reach = (a) => modules.filter((m) => m.from.some((f) => a.files.includes(f))).length;
247
+ return [...byKey.values()].sort((a, b) => reach(b) - reach(a) || b.files.length - a.files.length || a.label.localeCompare(b.label));
248
+ }
249
+ /** Convenience wrapper: build the module index from a context dir. */
250
+ export function blastRadiusIn(graph, contextDir, changed, basis, depth) {
251
+ return blastRadius(graph, changed, basis, { depth, modules: moduleIndex(contextDir) });
252
+ }
253
+ function hasNode(h) {
254
+ // Unresolved endpoints (an import module string no node exists for) carry no
255
+ // location, so they can neither be grouped nor opened — dropped rather than
256
+ // rendered as a box with no file behind it.
257
+ return h.node !== null;
258
+ }
259
+ function toImpacted(h) {
260
+ return {
261
+ id: h.node.id, name: h.node.name, kind: h.node.kind,
262
+ path: h.node.path, span: h.node.span, relation: h.relation, depth: h.depth,
263
+ };
264
+ }
265
+ function emptyIndex() {
266
+ return { hasConcepts: false, labelOf: (p) => p, conceptOf: () => null };
267
+ }
268
+ /**
269
+ * The concept claiming EVERY file in a cluster, or null when they disagree.
270
+ *
271
+ * Unanimity is the point: a concept that covers three of five files describes
272
+ * something narrower than the cluster, and stamping its name on the whole thing is
273
+ * how a diagram starts lying about what it drew.
274
+ */
275
+ function sharedConcept(paths, index) {
276
+ const concepts = new Set(paths.map((p) => index.conceptOf(p)));
277
+ const [only] = concepts;
278
+ return concepts.size === 1 && only ? shortLabel(only) : null;
279
+ }
280
+ /**
281
+ * The deterministic backstop label: the cluster's most significant symbol.
282
+ *
283
+ * Reached with no concept, no cache and no API key, so this is what guarantees a
284
+ * circle never carries a bare directory. It is a fact rather than a guess — the
285
+ * reviewer can grep the name — which is why it beats borrowing a neighbouring
286
+ * concept: on graft's own graph that borrowing labelled the freshness gate
287
+ * "Graph Extraction and Loading", which misleads worse than any path.
288
+ */
289
+ export function hubLabel(names, fallback) {
290
+ const [head] = names.filter(Boolean);
291
+ // The hub alone, with no "+8" tail: how many symbols came with it is already the
292
+ // circle's second line and the table's own column, and repeating it in the label
293
+ // turned "writeGraph" into "writeGraph +8", which reads as a version number.
294
+ return head ? shortLabel(head) : fallback;
295
+ }
296
+ /**
297
+ * Group dependents into modules. `origins` carries, per dependent, the changed
298
+ * files whose walk actually reached it — so a module's `from` is the real arrow
299
+ * set, not every changed file in the PR.
300
+ */
301
+ function groupByModule(impacted, changed, origins, modules) {
302
+ const changedPaths = new Set(changed.map((c) => c.path));
303
+ const byKey = new Map();
304
+ for (const hit of impacted) {
305
+ // A dependent inside a file the PR already changes is not "reach" — it is the
306
+ // diff. Reviewers see it in the diff itself; repeating it as blast radius is
307
+ // what makes these comments feel like noise.
308
+ if (changedPaths.has(hit.path))
309
+ continue;
310
+ // Cluster by concept where one exists, else by directory. Clustering and
311
+ // LABELLING are separate steps now: the key only has to be stable, while the
312
+ // label goes through the ladder below and may end up naming a symbol.
313
+ const key = modules.conceptOf(hit.path) ?? dirLabel(hit.path);
314
+ let mod = byKey.get(key);
315
+ if (!mod) {
316
+ mod = { label: key, labelSource: "symbol", key, files: [], symbols: [], from: [] };
317
+ byKey.set(key, mod);
318
+ }
319
+ mod.symbols.push(hit);
320
+ if (!mod.files.includes(hit.path))
321
+ mod.files.push(hit.path);
322
+ }
323
+ for (const mod of byKey.values()) {
324
+ const from = new Set();
325
+ for (const s of mod.symbols)
326
+ for (const p of origins.get(s.id) ?? [])
327
+ from.add(p);
328
+ mod.from = [...from].sort();
329
+ mod.files.sort();
330
+ mod.symbols.sort((a, b) => a.depth - b.depth || a.path.localeCompare(b.path));
331
+ // Shallowest symbol first after that sort, so it is the cluster's hub: the
332
+ // thing one hop from the diff rather than an arbitrary member.
333
+ const concept = sharedConcept(mod.files, modules);
334
+ mod.label = concept ?? hubLabel(mod.symbols.map((s) => s.name), mod.key);
335
+ mod.labelSource = concept ? "concept" : "symbol";
336
+ }
337
+ // Test-only modules are separated, not just sorted last. On a repo with a test
338
+ // per module they are the majority of the graph's dependents — graft's own 24-file
339
+ // PR produced 31 modules, 24 of them a single test file — so leaving them in the
340
+ // same list means they crowd out every module a reviewer needs whatever the caps
341
+ // are. "Your tests reference the thing you changed" is one line, not 24 sections.
342
+ const bySize = (a, b) => b.symbols.length - a.symbols.length || a.label.localeCompare(b.label);
343
+ const all = [...byKey.values()];
344
+ return {
345
+ modules: all.filter((m) => !isTestOnly(m)).sort(bySize),
346
+ testModules: all.filter(isTestOnly).sort(bySize),
347
+ };
348
+ }
349
+ /**
350
+ * Directory groups the diff is folded down to before anything is drawn.
351
+ *
352
+ * Kept here rather than in the renderer because it is a statement about the diff,
353
+ * not about the picture: five areas is roughly what a reviewer holds in their head,
354
+ * and the renderer then draws all of them.
355
+ */
356
+ const MAX_AREAS = 5;
357
+ /**
358
+ * Fold directory groups into their parents until there are at most `max`.
359
+ *
360
+ * The deepest group goes first, and only into a parent that already exists, so
361
+ * `src/ai/llm/` joins `src/ai/` rather than everything collapsing towards the repo
362
+ * root. When no group has an existing parent, one is created — but never at the top
363
+ * level, since a single `(root)` area is no grouping at all.
364
+ */
365
+ function coarsen(groups, max) {
366
+ const depth = (dir) => dir.split("/").length;
367
+ while (groups.size > max) {
368
+ const keys = [...groups.keys()].sort((a, b) => depth(b) - depth(a) || (groups.get(a).length - groups.get(b).length));
369
+ const pick = keys.find((k) => groups.has(parentDir(k)) && parentDir(k) !== "") ??
370
+ keys.find((k) => parentDir(k) !== "");
371
+ if (!pick)
372
+ return;
373
+ const parent = parentDir(pick);
374
+ groups.set(parent, [...(groups.get(parent) ?? []), ...groups.get(pick)]);
375
+ groups.delete(pick);
376
+ }
377
+ }
378
+ const TEST_PATH = /(^|\/)(tests?|specs?|__tests__)\/|\.(test|spec)\.[cm]?[jt]sx?$|_test\.(go|py|rb)$/i;
379
+ /** True when every file in the module is a test file. */
380
+ function isTestOnly(mod) {
381
+ return mod.files.length > 0 && mod.files.every((f) => TEST_PATH.test(f));
382
+ }
383
+ //# sourceMappingURL=blast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blast.js","sourceRoot":"","sources":["../../src/blast/blast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ export type ChangeStatus = "added" | "modified" | "deleted" | "renamed";
2
+ /** A contiguous run of changed lines, in POST-image (new file) line numbers. */
3
+ export interface LineRange {
4
+ start: number;
5
+ end: number;
6
+ }
7
+ /**
8
+ * One line git reported inside a hunk.
9
+ *
10
+ * `n` is the POST-image number, so it is the number a reviewer sees in the file
11
+ * on disk — a deleted line has none.
12
+ */
13
+ export interface DiffLine {
14
+ n: number | null;
15
+ sign: "+" | "-";
16
+ text: string;
17
+ }
18
+ /** A hunk's range and the lines in it. `ranges` on the file mirrors these. */
19
+ export interface Hunk extends LineRange {
20
+ lines: DiffLine[];
21
+ /** Lines dropped by the per-hunk cap — a generated file is not worth holding. */
22
+ dropped: number;
23
+ }
24
+ export interface ChangedFile {
25
+ /** Repo-relative posix path, post-image (the new name for a rename). */
26
+ path: string;
27
+ status: ChangeStatus;
28
+ /** Pre-image path, renames only. */
29
+ oldPath?: string;
30
+ /** Post-image changed line ranges. Empty for a pure delete or a mode-only change. */
31
+ ranges: LineRange[];
32
+ /** The same hunks, carrying their text: what a panel shows so a reader sees the
33
+ * change rather than a line number they have to go look up. One per range. */
34
+ hunks: Hunk[];
35
+ }
36
+ export interface DiffResult {
37
+ /** Human label for what was compared, e.g. "origin/main...HEAD". */
38
+ basis: string;
39
+ files: ChangedFile[];
40
+ }
41
+ /** True when `ref` names something git can resolve — checked before diffing so
42
+ * an unknown `--base` fails with a caller-facing message, not a git stack. */
43
+ export declare function refExists(root: string, ref: string): boolean;
44
+ /**
45
+ * Changed files + post-image line ranges.
46
+ *
47
+ * With no `base` this reports the working tree against HEAD (the local
48
+ * "what am I about to push" case), falling back to the last commit when the
49
+ * tree is clean — so the command answers something useful when run by hand,
50
+ * and CI passes `--base` for the real PR range.
51
+ */
52
+ export declare function changedFiles(root: string, base?: string): DiffResult | null;
53
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/blast/diff.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;AAExE,gFAAgF;AAChF,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjB,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8EAA8E;AAC9E,MAAM,WAAW,IAAK,SAAQ,SAAS;IACrC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB;kFAC8E;IAC9E,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAsBD;8EAC8E;AAC9E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE5D;AAcD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAe3E"}