sverklo 0.2.12 → 0.2.14

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 (116) hide show
  1. package/README.md +102 -13
  2. package/dist/bin/sverklo.js +69 -1
  3. package/dist/bin/sverklo.js.map +1 -1
  4. package/dist/src/audit-prompt.d.ts +2 -0
  5. package/dist/src/audit-prompt.js +91 -0
  6. package/dist/src/audit-prompt.js.map +1 -0
  7. package/dist/src/doctor.js +55 -0
  8. package/dist/src/doctor.js.map +1 -1
  9. package/dist/src/indexer/embedding-providers.d.ts +34 -0
  10. package/dist/src/indexer/embedding-providers.js +215 -0
  11. package/dist/src/indexer/embedding-providers.js.map +1 -0
  12. package/dist/src/indexer/embedding-providers.test.d.ts +1 -0
  13. package/dist/src/indexer/embedding-providers.test.js +83 -0
  14. package/dist/src/indexer/embedding-providers.test.js.map +1 -0
  15. package/dist/src/indexer/indexer-freshness.test.d.ts +1 -0
  16. package/dist/src/indexer/indexer-freshness.test.js +109 -0
  17. package/dist/src/indexer/indexer-freshness.test.js.map +1 -0
  18. package/dist/src/indexer/indexer-provider-integration.test.d.ts +1 -0
  19. package/dist/src/indexer/indexer-provider-integration.test.js +142 -0
  20. package/dist/src/indexer/indexer-provider-integration.test.js.map +1 -0
  21. package/dist/src/indexer/indexer.d.ts +44 -0
  22. package/dist/src/indexer/indexer.js +153 -10
  23. package/dist/src/indexer/indexer.js.map +1 -1
  24. package/dist/src/indexer/migration.test.d.ts +1 -0
  25. package/dist/src/indexer/migration.test.js +144 -0
  26. package/dist/src/indexer/migration.test.js.map +1 -0
  27. package/dist/src/indexer/symbol-extractor.js +17 -5
  28. package/dist/src/indexer/symbol-extractor.js.map +1 -1
  29. package/dist/src/indexer/symbol-extractor.test.d.ts +1 -0
  30. package/dist/src/indexer/symbol-extractor.test.js +88 -0
  31. package/dist/src/indexer/symbol-extractor.test.js.map +1 -0
  32. package/dist/src/indexer/watcher.js +4 -0
  33. package/dist/src/indexer/watcher.js.map +1 -1
  34. package/dist/src/memory/journal.d.ts +62 -0
  35. package/dist/src/memory/journal.js +136 -0
  36. package/dist/src/memory/journal.js.map +1 -0
  37. package/dist/src/memory/journal.test.d.ts +1 -0
  38. package/dist/src/memory/journal.test.js +98 -0
  39. package/dist/src/memory/journal.test.js.map +1 -0
  40. package/dist/src/modes.d.ts +16 -0
  41. package/dist/src/modes.js +104 -0
  42. package/dist/src/modes.js.map +1 -0
  43. package/dist/src/modes.test.d.ts +1 -0
  44. package/dist/src/modes.test.js +48 -0
  45. package/dist/src/modes.test.js.map +1 -0
  46. package/dist/src/search/hybrid-search.d.ts +22 -0
  47. package/dist/src/search/hybrid-search.js +169 -7
  48. package/dist/src/search/hybrid-search.js.map +1 -1
  49. package/dist/src/search/hybrid-search.test.d.ts +1 -0
  50. package/dist/src/search/hybrid-search.test.js +112 -0
  51. package/dist/src/search/hybrid-search.test.js.map +1 -0
  52. package/dist/src/search/token-budget.d.ts +1 -0
  53. package/dist/src/search/token-budget.js +34 -6
  54. package/dist/src/search/token-budget.js.map +1 -1
  55. package/dist/src/server/mcp-server.js +32 -25
  56. package/dist/src/server/mcp-server.js.map +1 -1
  57. package/dist/src/server/tool-overrides.d.ts +16 -0
  58. package/dist/src/server/tool-overrides.js +102 -0
  59. package/dist/src/server/tool-overrides.js.map +1 -0
  60. package/dist/src/server/tool-overrides.test.d.ts +1 -0
  61. package/dist/src/server/tool-overrides.test.js +124 -0
  62. package/dist/src/server/tool-overrides.test.js.map +1 -0
  63. package/dist/src/server/tools/context-budget.test.d.ts +1 -0
  64. package/dist/src/server/tools/context-budget.test.js +150 -0
  65. package/dist/src/server/tools/context-budget.test.js.map +1 -0
  66. package/dist/src/server/tools/context.d.ts +11 -1
  67. package/dist/src/server/tools/context.js +202 -8
  68. package/dist/src/server/tools/context.js.map +1 -1
  69. package/dist/src/server/tools/diff-heuristics.d.ts +28 -0
  70. package/dist/src/server/tools/diff-heuristics.js +213 -0
  71. package/dist/src/server/tools/diff-heuristics.js.map +1 -0
  72. package/dist/src/server/tools/diff-heuristics.test.d.ts +1 -0
  73. package/dist/src/server/tools/diff-heuristics.test.js +151 -0
  74. package/dist/src/server/tools/diff-heuristics.test.js.map +1 -0
  75. package/dist/src/server/tools/find-references.d.ts +4 -0
  76. package/dist/src/server/tools/find-references.js +46 -6
  77. package/dist/src/server/tools/find-references.js.map +1 -1
  78. package/dist/src/server/tools/find-references.test.d.ts +1 -0
  79. package/dist/src/server/tools/find-references.test.js +98 -0
  80. package/dist/src/server/tools/find-references.test.js.map +1 -0
  81. package/dist/src/server/tools/forget.js +3 -0
  82. package/dist/src/server/tools/forget.js.map +1 -1
  83. package/dist/src/server/tools/index-status.js +16 -0
  84. package/dist/src/server/tools/index-status.js.map +1 -1
  85. package/dist/src/server/tools/lookup.js +21 -13
  86. package/dist/src/server/tools/lookup.js.map +1 -1
  87. package/dist/src/server/tools/lookup.test.d.ts +1 -0
  88. package/dist/src/server/tools/lookup.test.js +110 -0
  89. package/dist/src/server/tools/lookup.test.js.map +1 -0
  90. package/dist/src/server/tools/recall.d.ts +5 -1
  91. package/dist/src/server/tools/recall.js +68 -6
  92. package/dist/src/server/tools/recall.js.map +1 -1
  93. package/dist/src/server/tools/recall.test.d.ts +1 -0
  94. package/dist/src/server/tools/recall.test.js +116 -0
  95. package/dist/src/server/tools/recall.test.js.map +1 -0
  96. package/dist/src/server/tools/remember.js +16 -2
  97. package/dist/src/server/tools/remember.js.map +1 -1
  98. package/dist/src/server/tools/review-diff.js +31 -0
  99. package/dist/src/server/tools/review-diff.js.map +1 -1
  100. package/dist/src/server/tools/search.js +29 -4
  101. package/dist/src/server/tools/search.js.map +1 -1
  102. package/dist/src/server/tools/search.test.d.ts +1 -0
  103. package/dist/src/server/tools/search.test.js +118 -0
  104. package/dist/src/server/tools/search.test.js.map +1 -0
  105. package/dist/src/server/tools/tier.js +25 -1
  106. package/dist/src/server/tools/tier.js.map +1 -1
  107. package/dist/src/storage/chunk-store.d.ts +12 -0
  108. package/dist/src/storage/chunk-store.js +16 -0
  109. package/dist/src/storage/chunk-store.js.map +1 -1
  110. package/dist/src/storage/chunk-store.test.d.ts +1 -0
  111. package/dist/src/storage/chunk-store.test.js +69 -0
  112. package/dist/src/storage/chunk-store.test.js.map +1 -0
  113. package/dist/src/storage/database.d.ts +13 -0
  114. package/dist/src/storage/database.js +47 -0
  115. package/dist/src/storage/database.js.map +1 -1
  116. package/package.json +5 -2
@@ -12,39 +12,65 @@
12
12
  // full — normal + dependency neighbours of top results
13
13
  import { hybridSearch } from "../../search/hybrid-search.js";
14
14
  import { handleRecall } from "./recall.js";
15
+ import { estimateTokens } from "../../utils/tokens.js";
15
16
  export const contextTool = {
16
17
  name: "sverklo_context",
17
18
  description: "Umbrella context bundler. Give a task description and get a single curated bundle: " +
18
19
  "codebase overview header, semantically relevant code, related symbols, and matching " +
19
20
  "saved memories — in one round trip. Use this as the FIRST call when you start working " +
20
- "on a new task and want to orient quickly. Drill down with the atomic tools (search, " +
21
- "lookup, refs, recall) only after this.",
21
+ "on a new task and want to orient quickly. " +
22
+ "PASS `budget` for a PageRank-pruned repo map fit to a token budget — the ideal way " +
23
+ "to give an agent a complete mental model of an unfamiliar codebase in one call.",
22
24
  inputSchema: {
23
25
  type: "object",
24
26
  properties: {
25
27
  task: {
26
28
  type: "string",
27
- description: "Free-form description of what you're trying to do, e.g. 'add rate limiting to the login endpoint' or 'understand how billing webhooks are processed'.",
29
+ description: "Free-form description of what you're trying to do, e.g. 'add rate limiting to the login endpoint' or 'understand how billing webhooks are processed'. When `budget` is set and no task is given, returns a pure PageRank-ordered repo map.",
28
30
  },
29
31
  detail_level: {
30
32
  type: "string",
31
33
  enum: ["minimal", "normal", "full"],
32
- description: "How much to return. minimal=fast/cheap (good for snap orientation); normal=balanced (default); full=adds dependency neighbours.",
34
+ description: "How much to return. minimal=fast/cheap (good for snap orientation); normal=balanced (default); full=adds dependency neighbours. Ignored when `budget` is set.",
33
35
  },
34
36
  scope: {
35
37
  type: "string",
36
38
  description: "Optional path prefix to constrain the search (e.g. 'src/api/').",
37
39
  },
40
+ budget: {
41
+ type: "number",
42
+ description: "When set, returns a PageRank-pruned repo map greedily filled to this token budget (inspired by aider's repo-map). Files are ordered by PageRank importance, optionally biased toward `task`. Only symbol signatures are rendered — use the atomic tools for full bodies. Typical values: 4000 (snap map), 8000 (full mental model), 16000 (deep context).",
43
+ },
44
+ exclude: {
45
+ type: "array",
46
+ items: { type: "string" },
47
+ description: "Path substrings to exclude from the repo map (e.g. ['test', 'migration']).",
48
+ },
38
49
  },
39
- required: ["task"],
40
50
  },
41
51
  };
42
52
  export async function handleContext(indexer, args) {
43
- const task = args.task?.trim();
44
- if (!task)
45
- return "Error: `task` is required.";
53
+ const task = args.task?.trim() || "";
46
54
  const detail = (args.detail_level || "normal");
47
55
  const scope = args.scope;
56
+ const budget = args.budget;
57
+ const exclude = args.exclude || [];
58
+ // ── Budget mode: PageRank-pruned repo map (issue #8) ──────────────
59
+ // When budget is set, we skip the standard search-based bundler and
60
+ // instead build a dense structural map greedily filled to the target
61
+ // token count. This is the "give the agent a complete mental model
62
+ // of an unfamiliar repo in one call" path — aider's repo-map pattern.
63
+ if (typeof budget === "number" && budget > 0) {
64
+ return await buildPrunedRepoMap(indexer, {
65
+ budget,
66
+ task,
67
+ scope,
68
+ exclude,
69
+ });
70
+ }
71
+ if (!task) {
72
+ return "Error: `task` is required (unless you pass `budget` for a pure repo map).";
73
+ }
48
74
  const searchLimit = detail === "minimal" ? 3 : detail === "normal" ? 5 : 8;
49
75
  const memoryLimit = detail === "minimal" ? 2 : 5;
50
76
  const tokenBudget = detail === "minimal" ? 1500 : detail === "normal" ? 3000 : 5000;
@@ -159,4 +185,172 @@ export async function handleContext(indexer, args) {
159
185
  }
160
186
  return parts.join("\n");
161
187
  }
188
+ // ─────────────────────────────────────────────────────────────────────
189
+ // Issue #8 — PageRank-pruned repo map fit to a token budget.
190
+ //
191
+ // Design (mirrors aider's repo-map, adapted to sverklo's symbol graph):
192
+ //
193
+ // 1. Rank files by PageRank DESC.
194
+ // 2. If a task was provided, run a semantic search and upweight files
195
+ // that contain strong matches. This lets the map center on the
196
+ // subsystem the user is working in, instead of always the global
197
+ // hub files.
198
+ // 3. Walk files in ranked order; for each, render signatures of its
199
+ // most important symbols (also ordered by PageRank proxy).
200
+ // 4. Greedily fill the budget. Stop the instant adding the next file
201
+ // would exceed the cap. The output is deterministic given the
202
+ // same index state and budget — important for caching.
203
+ //
204
+ // Determinism note: we break PageRank ties by file path to keep output
205
+ // stable across runs of the same input. This matters for caching and
206
+ // snapshot-testing downstream.
207
+ // ─────────────────────────────────────────────────────────────────────
208
+ // Upper bound on the repo-map budget. Anything above 32k tokens is
209
+ // almost certainly a mistake — the resulting map won't fit in any
210
+ // current model's context window and the wall-clock cost of walking
211
+ // every file climbs linearly. We cap and emit a warning in the
212
+ // output so the caller knows we trimmed.
213
+ const MAX_REPO_MAP_BUDGET = 32000;
214
+ const MIN_REPO_MAP_BUDGET = 500;
215
+ async function buildPrunedRepoMap(indexer, opts) {
216
+ let { budget } = opts;
217
+ const { task, scope, exclude } = opts;
218
+ // Clamp the budget to sane bounds. Sub-500 can't even fit a header
219
+ // + one file meaningfully; over 32k is nearly always unintentional.
220
+ let budgetWarning = "";
221
+ if (budget > MAX_REPO_MAP_BUDGET) {
222
+ budgetWarning = `_Budget ${budget} exceeded max ${MAX_REPO_MAP_BUDGET} — clamped. For larger maps, use multiple scoped calls._\n\n`;
223
+ budget = MAX_REPO_MAP_BUDGET;
224
+ }
225
+ else if (budget < MIN_REPO_MAP_BUDGET) {
226
+ return (`Budget too small: ${budget}. Minimum is ${MIN_REPO_MAP_BUDGET} tokens — ` +
227
+ `below that the repo map can't fit a useful number of files. ` +
228
+ `Try \`budget: ${MIN_REPO_MAP_BUDGET}\` for a snap view.`);
229
+ }
230
+ // Pull all files sorted by PageRank. file_store.getAll() already
231
+ // returns them in pagerank DESC order — see storage/file-store.ts.
232
+ let files = indexer.fileStore.getAll();
233
+ // Apply scope prefix and exclude substrings.
234
+ if (scope) {
235
+ files = files.filter((f) => f.path.startsWith(scope));
236
+ }
237
+ if (exclude.length > 0) {
238
+ files = files.filter((f) => !exclude.some((ex) => f.path.includes(ex)));
239
+ }
240
+ // Task-biased reranking: if the caller gave us a task, run a search
241
+ // and boost files that contain strong matches. We keep the PageRank
242
+ // signal as the primary order and only use the task signal as a
243
+ // tiebreaker / boost — so the output is still dominated by the
244
+ // structural importance of the codebase, not by query noise.
245
+ const taskBoost = new Map();
246
+ if (task) {
247
+ try {
248
+ const hits = await hybridSearch(indexer, {
249
+ query: task,
250
+ tokenBudget: 50000, // ask for a lot so boost is meaningful
251
+ scope,
252
+ type: "any",
253
+ });
254
+ // Accumulate score per file across all hits.
255
+ for (const h of hits) {
256
+ taskBoost.set(h.chunk.file_id, (taskBoost.get(h.chunk.file_id) || 0) + h.score);
257
+ }
258
+ }
259
+ catch {
260
+ // Fall back to pure PageRank if search fails — never block the map.
261
+ }
262
+ }
263
+ // Stable ranking: compose PageRank with the task boost, break ties
264
+ // by path so the same input always produces the same output.
265
+ const ranked = [...files].sort((a, b) => {
266
+ const ba = (taskBoost.get(a.id) || 0) * 0.5 + a.pagerank;
267
+ const bb = (taskBoost.get(b.id) || 0) * 0.5 + b.pagerank;
268
+ if (bb !== ba)
269
+ return bb - ba;
270
+ return a.path.localeCompare(b.path);
271
+ });
272
+ // Header first so the caller can still see the budget and ordering
273
+ // even when the budget is tiny and zero files fit.
274
+ const parts = [];
275
+ parts.push(`# Repo map${task ? ` · centered on: ${task}` : ""}${scope ? ` · scope: ${scope}` : ""}`);
276
+ parts.push(`_Budget: ${budget} tokens · ordered by PageRank${task ? " + task relevance" : ""}._`);
277
+ if (budgetWarning)
278
+ parts.push(budgetWarning);
279
+ parts.push("");
280
+ // Remaining budget after the header. 10% cushion for the trailing
281
+ // footer text and any rendering slack. Token estimates are rough —
282
+ // we use the same estimator as the indexer (chars / 3.5).
283
+ const headerCost = estimateTokens(parts.join("\n"));
284
+ let remaining = budget - headerCost - 100;
285
+ let filesRendered = 0;
286
+ let filesSkipped = 0;
287
+ for (const file of ranked) {
288
+ if (remaining <= 0) {
289
+ filesSkipped = ranked.length - filesRendered;
290
+ break;
291
+ }
292
+ // Pull the file's symbols. We only render symbol signatures
293
+ // (cheap) plus the symbol's name and type. Full bodies would
294
+ // blow the budget instantly — the point of a map is to be a
295
+ // legend, not the terrain.
296
+ const chunks = indexer.chunkStore
297
+ .getByFile(file.id)
298
+ .filter((c) => c.name);
299
+ if (chunks.length === 0)
300
+ continue;
301
+ // Render the file's entry. Symbols are ordered as they appear in
302
+ // the file (by start_line). Top-level types/classes come first in
303
+ // most codebases so this matches how a human skims.
304
+ const fileHeader = `## \`${file.path}\` · PR ${file.pagerank.toFixed(3)} · ${file.language || "?"}`;
305
+ const fileLines = [fileHeader];
306
+ // Soft cap on symbols-per-file so one massive file doesn't eat the
307
+ // whole budget. Files with >40 symbols render as "+ N more".
308
+ const CAP_PER_FILE = 40;
309
+ const shown = chunks.slice(0, CAP_PER_FILE);
310
+ for (const c of shown) {
311
+ const sig = c.signature ? c.signature.trim() : `${c.type} ${c.name}`;
312
+ // Keep each line short — the map should scan like an outline.
313
+ const truncated = sig.length > 110 ? sig.slice(0, 107) + "..." : sig;
314
+ fileLines.push(`- ${truncated}`);
315
+ }
316
+ if (chunks.length > CAP_PER_FILE) {
317
+ fileLines.push(`- _...and ${chunks.length - CAP_PER_FILE} more symbols_`);
318
+ }
319
+ const entry = fileLines.join("\n") + "\n";
320
+ const cost = estimateTokens(entry);
321
+ // If a single file's entry exceeds the remaining budget, render a
322
+ // truncated version (just the header + symbol count) so the caller
323
+ // still knows the file exists. Never render a partial entry with
324
+ // half its symbols cut off — that's confusing.
325
+ if (cost > remaining) {
326
+ const fallback = `## \`${file.path}\` · PR ${file.pagerank.toFixed(3)}\n` +
327
+ `- _${chunks.length} symbols (budget exhausted — use sverklo_lookup for details)_\n`;
328
+ const fallbackCost = estimateTokens(fallback);
329
+ if (fallbackCost <= remaining) {
330
+ parts.push(fallback);
331
+ remaining -= fallbackCost;
332
+ filesRendered++;
333
+ }
334
+ else {
335
+ filesSkipped = ranked.length - filesRendered;
336
+ break;
337
+ }
338
+ }
339
+ else {
340
+ parts.push(entry);
341
+ remaining -= cost;
342
+ filesRendered++;
343
+ }
344
+ }
345
+ // Footer
346
+ parts.push("");
347
+ parts.push(`_Rendered ${filesRendered} of ${ranked.length} files` +
348
+ (filesSkipped > 0
349
+ ? ` (${filesSkipped} skipped — budget exhausted; raise \`budget\` to see more)_`
350
+ : "_"));
351
+ if (filesRendered > 0) {
352
+ parts.push("_Use `sverklo_lookup name:<symbol>` or `sverklo_search query:<...>` to drill into any symbol._");
353
+ }
354
+ return parts.join("\n");
355
+ }
162
356
  //# sourceMappingURL=context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/server/tools/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/server/tools/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface DiffHunk {
2
+ filePath: string;
3
+ oldStart: number;
4
+ newStart: number;
5
+ /** Every line in the hunk, including context. Each entry is "+ ", "- ", " " followed by content. */
6
+ lines: string[];
7
+ }
8
+ export interface HeuristicFinding {
9
+ heuristic: string;
10
+ severity: "high" | "medium" | "low";
11
+ file: string;
12
+ line: number;
13
+ snippet: string;
14
+ message: string;
15
+ }
16
+ export declare function findUnguardedStreamCalls(hunks: DiffHunk[]): HeuristicFinding[];
17
+ export declare const ALL_HEURISTICS: ((hunks: DiffHunk[]) => HeuristicFinding[])[];
18
+ export declare function runAllHeuristics(hunks: DiffHunk[]): HeuristicFinding[];
19
+ /**
20
+ * Parse a unified-diff string (output of `git diff -U5 ref`) into hunks.
21
+ * Very permissive — anything that doesn't match the expected header is
22
+ * skipped rather than raising.
23
+ */
24
+ export declare function parseUnifiedDiff(diffText: string): DiffHunk[];
25
+ /**
26
+ * Convenience: pull a unified diff from git and parse it.
27
+ */
28
+ export declare function getDiffHunks(rootPath: string, ref: string): DiffHunk[];
@@ -0,0 +1,213 @@
1
+ // Structural heuristics that scan the actual diff text for specific classes
2
+ // of risk that symbol-level analysis alone will not catch. Kept as a
3
+ // separate module so new heuristics can be added without touching the
4
+ // main review-diff handler, and so each heuristic is unit-testable in
5
+ // isolation.
6
+ //
7
+ // Heuristics are *heuristics* — they trade some false positives for
8
+ // recall on real-world bugs. Each one attaches a short "why" so a human
9
+ // reviewer can quickly dismiss a false flag.
10
+ //
11
+ // Current heuristics:
12
+ // - unguarded-stream-call: a new call site introduced inside a stream
13
+ // pipeline (.map / .forEach / .flatMap / .filter / .reduce / etc.)
14
+ // where the enclosing function has no visible try-catch. One
15
+ // uncaught RuntimeException on a single element will abort the
16
+ // entire stream — a real outage risk on production read paths.
17
+ // Tracked in github.com/sverklo/sverklo/issues/5.
18
+ //
19
+ // Adding a heuristic:
20
+ // 1. Write a pure function that takes a DiffHunk[] and returns
21
+ // HeuristicFinding[]. No I/O, no git, no filesystem — the caller
22
+ // is responsible for producing hunks.
23
+ // 2. Register it in ALL_HEURISTICS below.
24
+ // 3. Unit-test it with representative fixtures.
25
+ import { execSync } from "node:child_process";
26
+ // ────────────────────────────────────────────────────────────────────
27
+ // Heuristic 1 — unguarded stream-pipeline call
28
+ // ────────────────────────────────────────────────────────────────────
29
+ // Stream pipeline markers we care about. The list is deliberately
30
+ // multi-language: Java / TS / Kotlin / Scala all share the same shape.
31
+ const STREAM_METHODS = [
32
+ "map",
33
+ "forEach",
34
+ "flatMap",
35
+ "filter",
36
+ "reduce",
37
+ "mapToInt",
38
+ "mapToLong",
39
+ "mapToDouble",
40
+ "peek",
41
+ "collect",
42
+ ];
43
+ // A line is "entering a stream pipeline" if it matches `.<method>(`
44
+ // where <method> is one of the above. We accept optional whitespace.
45
+ const STREAM_ENTRY_RE = new RegExp(`\\.(${STREAM_METHODS.join("|")})\\s*\\(`);
46
+ // A line looks like a call that may throw if it contains `.<name>(`
47
+ // for an identifier-shaped name. This is broad on purpose — most method
48
+ // calls *can* throw, so any introduced call inside a stream pipeline
49
+ // without a try-catch is the pattern we want to flag.
50
+ const ANY_CALL_RE = /\b\w+\s*\(/;
51
+ // A try-catch is "visible" in the hunk if we see a `try` or `catch`
52
+ // token on any context line. This is a conservative proxy for "the
53
+ // enclosing method catches its exceptions" — an AST-based check would
54
+ // be more accurate but would require parsing the entire file per diff.
55
+ const TRY_OR_CATCH_RE = /\b(try|catch)\b/;
56
+ export function findUnguardedStreamCalls(hunks) {
57
+ const findings = [];
58
+ for (const hunk of hunks) {
59
+ // Is there a visible try / catch anywhere in the hunk's context?
60
+ // If so, skip the whole hunk — the enclosing method probably
61
+ // catches. False negatives here are fine; we care about loud wins.
62
+ const hasTryCatch = hunk.lines.some((l) => TRY_OR_CATCH_RE.test(l));
63
+ if (hasTryCatch)
64
+ continue;
65
+ // Walk the hunk line by line. Track whether we've seen a stream
66
+ // entry on a preceding context/added line, and whether we're still
67
+ // "inside" it (approximated by nesting depth on the same or next
68
+ // lines in the hunk).
69
+ let insideStreamDepth = 0;
70
+ let streamFileLine = hunk.newStart;
71
+ let currentNewLine = hunk.newStart;
72
+ for (const rawLine of hunk.lines) {
73
+ const prefix = rawLine.charAt(0);
74
+ const content = rawLine.slice(1);
75
+ // Track whether we're in a stream block, using a crude brace count
76
+ // scoped to the hunk. This misses pipelines that span more than the
77
+ // hunk window — we accept that as a recall tradeoff.
78
+ if (STREAM_ENTRY_RE.test(content)) {
79
+ insideStreamDepth = 1;
80
+ streamFileLine = currentNewLine;
81
+ }
82
+ else if (insideStreamDepth > 0) {
83
+ const opens = (content.match(/\(/g) || []).length;
84
+ const closes = (content.match(/\)/g) || []).length;
85
+ insideStreamDepth += opens - closes;
86
+ if (insideStreamDepth < 0)
87
+ insideStreamDepth = 0;
88
+ }
89
+ // Only flag on added lines (new risks), not context. Context
90
+ // lines merely help us track state.
91
+ if (prefix === "+" && insideStreamDepth > 0 && ANY_CALL_RE.test(content)) {
92
+ // Skip the stream-entry line itself — we only flag the *body*
93
+ // calls inside the pipeline, not the pipeline declaration.
94
+ if (!STREAM_ENTRY_RE.test(content)) {
95
+ findings.push({
96
+ heuristic: "unguarded-stream-call",
97
+ severity: "medium",
98
+ file: hunk.filePath,
99
+ line: currentNewLine,
100
+ snippet: content.trim().slice(0, 120),
101
+ message: "New call inside a stream pipeline with no visible try-catch in the hunk. " +
102
+ "A single RuntimeException on one element will abort the entire pipeline — " +
103
+ "on a production read path this is an outage. Wrap the lambda body in " +
104
+ "try-catch or pre-filter elements that could throw.",
105
+ });
106
+ // Flag once per stream block to avoid spamming — a block with
107
+ // ten calls is one finding, not ten.
108
+ insideStreamDepth = 0;
109
+ }
110
+ }
111
+ // Advance the running new-file line counter. Context and added
112
+ // lines both consume new-file line numbers; removed lines do not.
113
+ if (prefix === "+" || prefix === " ")
114
+ currentNewLine++;
115
+ }
116
+ }
117
+ return findings;
118
+ }
119
+ // ────────────────────────────────────────────────────────────────────
120
+ // Registry + driver
121
+ // ────────────────────────────────────────────────────────────────────
122
+ export const ALL_HEURISTICS = [
123
+ findUnguardedStreamCalls,
124
+ ];
125
+ export function runAllHeuristics(hunks) {
126
+ const all = [];
127
+ for (const fn of ALL_HEURISTICS) {
128
+ try {
129
+ all.push(...fn(hunks));
130
+ }
131
+ catch {
132
+ // One broken heuristic must not take down review. Swallow and move on.
133
+ }
134
+ }
135
+ return all;
136
+ }
137
+ // ────────────────────────────────────────────────────────────────────
138
+ // Parser — turn `git diff --unified=N` text into DiffHunk[]
139
+ // ────────────────────────────────────────────────────────────────────
140
+ /**
141
+ * Parse a unified-diff string (output of `git diff -U5 ref`) into hunks.
142
+ * Very permissive — anything that doesn't match the expected header is
143
+ * skipped rather than raising.
144
+ */
145
+ export function parseUnifiedDiff(diffText) {
146
+ const hunks = [];
147
+ const lines = diffText.split("\n");
148
+ let currentFile = null;
149
+ let currentHunk = null;
150
+ for (const line of lines) {
151
+ // New file header: "diff --git a/foo b/foo"
152
+ if (line.startsWith("diff --git ")) {
153
+ if (currentHunk) {
154
+ hunks.push(currentHunk);
155
+ currentHunk = null;
156
+ }
157
+ currentFile = null;
158
+ continue;
159
+ }
160
+ // "+++ b/path" gives us the new file path
161
+ if (line.startsWith("+++ ")) {
162
+ const path = line.slice(4).replace(/^b\//, "").trim();
163
+ currentFile = path === "/dev/null" ? null : path;
164
+ continue;
165
+ }
166
+ // Hunk header: "@@ -12,5 +34,7 @@ optional-context"
167
+ if (line.startsWith("@@ ")) {
168
+ if (currentHunk)
169
+ hunks.push(currentHunk);
170
+ const match = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
171
+ if (match && currentFile) {
172
+ currentHunk = {
173
+ filePath: currentFile,
174
+ oldStart: parseInt(match[1], 10),
175
+ newStart: parseInt(match[2], 10),
176
+ lines: [],
177
+ };
178
+ }
179
+ else {
180
+ currentHunk = null;
181
+ }
182
+ continue;
183
+ }
184
+ // Body lines: "+", "-", or " " prefixed
185
+ if (currentHunk && (line.startsWith("+") || line.startsWith("-") || line.startsWith(" "))) {
186
+ // Skip the file-metadata lines "+++" / "---" which we already handled above
187
+ if (line.startsWith("+++") || line.startsWith("---"))
188
+ continue;
189
+ currentHunk.lines.push(line);
190
+ }
191
+ }
192
+ if (currentHunk)
193
+ hunks.push(currentHunk);
194
+ return hunks;
195
+ }
196
+ /**
197
+ * Convenience: pull a unified diff from git and parse it.
198
+ */
199
+ export function getDiffHunks(rootPath, ref) {
200
+ try {
201
+ const out = execSync(`git diff --unified=10 ${ref}`, {
202
+ cwd: rootPath,
203
+ encoding: "utf-8",
204
+ timeout: 8000,
205
+ maxBuffer: 10 * 1024 * 1024,
206
+ });
207
+ return parseUnifiedDiff(out);
208
+ }
209
+ catch {
210
+ return [];
211
+ }
212
+ }
213
+ //# sourceMappingURL=diff-heuristics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-heuristics.js","sourceRoot":"","sources":["../../../../src/server/tools/diff-heuristics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};