grepmax 0.18.1 → 0.19.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 (64) hide show
  1. package/README.md +27 -2
  2. package/dist/commands/add.js +4 -2
  3. package/dist/commands/claude-code.js +1 -1
  4. package/dist/commands/codex.js +3 -1
  5. package/dist/commands/dead.js +2 -6
  6. package/dist/commands/doctor.js +26 -7
  7. package/dist/commands/extract.js +3 -5
  8. package/dist/commands/impact.js +6 -4
  9. package/dist/commands/index.js +7 -2
  10. package/dist/commands/log.js +4 -2
  11. package/dist/commands/mcp.js +587 -715
  12. package/dist/commands/peek.js +15 -9
  13. package/dist/commands/plugin.js +1 -1
  14. package/dist/commands/project.js +15 -5
  15. package/dist/commands/related.js +8 -9
  16. package/dist/commands/review.js +1 -1
  17. package/dist/commands/similar.js +4 -4
  18. package/dist/commands/status.js +5 -3
  19. package/dist/commands/summarize.js +6 -4
  20. package/dist/commands/test-find.js +2 -2
  21. package/dist/commands/trace.js +12 -5
  22. package/dist/commands/watch.js +9 -5
  23. package/dist/eval-graph-nav.js +4 -1
  24. package/dist/eval-graph-recovery-probe.js +56 -14
  25. package/dist/eval-graph-spotcheck.js +10 -2
  26. package/dist/eval-graph-totals.js +5 -2
  27. package/dist/eval-oss.js +212 -37
  28. package/dist/eval-seed.js +13 -4
  29. package/dist/index.js +9 -9
  30. package/dist/lib/daemon/daemon.js +22 -13
  31. package/dist/lib/daemon/ipc-handler.js +18 -5
  32. package/dist/lib/daemon/mlx-server-manager.js +11 -3
  33. package/dist/lib/daemon/process-manager.js +1 -2
  34. package/dist/lib/daemon/watcher-manager.js +4 -4
  35. package/dist/lib/graph/callsites.js +151 -25
  36. package/dist/lib/index/batch-processor.js +6 -5
  37. package/dist/lib/index/chunker.js +2 -0
  38. package/dist/lib/index/syncer.js +7 -6
  39. package/dist/lib/llm/diff.js +56 -11
  40. package/dist/lib/llm/investigate.js +12 -5
  41. package/dist/lib/llm/review.js +21 -8
  42. package/dist/lib/llm/server.js +16 -7
  43. package/dist/lib/output/agent-search-formatter.js +25 -3
  44. package/dist/lib/output/index-state-footer.js +1 -1
  45. package/dist/lib/review/risk.js +2 -4
  46. package/dist/lib/search/searcher.js +37 -11
  47. package/dist/lib/search/seed-weight.js +4 -1
  48. package/dist/lib/skeleton/symbol-extractor.js +2 -1
  49. package/dist/lib/utils/cross-project.js +5 -1
  50. package/dist/lib/utils/daemon-client.js +5 -1
  51. package/dist/lib/utils/git.js +10 -2
  52. package/dist/lib/utils/project-registry.js +3 -2
  53. package/dist/lib/utils/scope-filter.js +3 -1
  54. package/dist/lib/utils/watcher-launcher.js +4 -1
  55. package/dist/lib/utils/watcher-store.js +2 -1
  56. package/dist/lib/workers/embeddings/mlx-client.js +7 -2
  57. package/dist/lib/workers/pool.js +9 -6
  58. package/dist/lib/workers/process-child.js +1 -1
  59. package/package.json +22 -19
  60. package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
  61. package/plugins/grepmax/hooks/cwd-changed.js +4 -1
  62. package/plugins/grepmax/hooks/pre-grep.js +2 -1
  63. package/plugins/grepmax/hooks/start.js +45 -10
  64. package/plugins/grepmax/hooks/subagent-start.js +1 -4
@@ -110,37 +110,163 @@ function resolveCallSites(callers, targetSymbol, fileCache = new Map()) {
110
110
  */
111
111
  const BUILTIN_CALLEES = new Set([
112
112
  // Object/primitive methods
113
- "toString", "valueOf", "hasOwnProperty",
113
+ "toString",
114
+ "valueOf",
115
+ "hasOwnProperty",
114
116
  // Array/String methods
115
- "push", "pop", "shift", "unshift", "slice", "splice", "concat", "join",
116
- "map", "filter", "reduce", "forEach", "find", "findIndex", "some", "every",
117
- "includes", "indexOf", "lastIndexOf", "sort", "reverse", "flat", "flatMap",
118
- "keys", "values", "entries", "fill",
119
- "split", "trim", "trimStart", "trimEnd", "replace", "replaceAll", "match",
120
- "matchAll", "test", "exec", "padStart", "padEnd", "repeat", "charAt",
121
- "charCodeAt", "codePointAt", "startsWith", "endsWith", "toLowerCase",
122
- "toUpperCase", "substring", "substr", "localeCompare", "normalize",
117
+ "push",
118
+ "pop",
119
+ "shift",
120
+ "unshift",
121
+ "slice",
122
+ "splice",
123
+ "concat",
124
+ "join",
125
+ "map",
126
+ "filter",
127
+ "reduce",
128
+ "forEach",
129
+ "find",
130
+ "findIndex",
131
+ "some",
132
+ "every",
133
+ "includes",
134
+ "indexOf",
135
+ "lastIndexOf",
136
+ "sort",
137
+ "reverse",
138
+ "flat",
139
+ "flatMap",
140
+ "keys",
141
+ "values",
142
+ "entries",
143
+ "fill",
144
+ "split",
145
+ "trim",
146
+ "trimStart",
147
+ "trimEnd",
148
+ "replace",
149
+ "replaceAll",
150
+ "match",
151
+ "matchAll",
152
+ "test",
153
+ "exec",
154
+ "padStart",
155
+ "padEnd",
156
+ "repeat",
157
+ "charAt",
158
+ "charCodeAt",
159
+ "codePointAt",
160
+ "startsWith",
161
+ "endsWith",
162
+ "toLowerCase",
163
+ "toUpperCase",
164
+ "substring",
165
+ "substr",
166
+ "localeCompare",
167
+ "normalize",
123
168
  // Map/Set methods
124
- "get", "set", "has", "add", "delete", "clear",
169
+ "get",
170
+ "set",
171
+ "has",
172
+ "add",
173
+ "delete",
174
+ "clear",
125
175
  // Math/Date/Number members
126
- "trunc", "floor", "ceil", "round", "abs", "min", "max", "random", "pow",
127
- "sqrt", "log2", "log10", "sign", "now", "parse", "parseInt", "parseFloat",
128
- "isInteger", "isFinite", "isNaN", "toFixed", "toISOString",
176
+ "trunc",
177
+ "floor",
178
+ "ceil",
179
+ "round",
180
+ "abs",
181
+ "min",
182
+ "max",
183
+ "random",
184
+ "pow",
185
+ "sqrt",
186
+ "log2",
187
+ "log10",
188
+ "sign",
189
+ "now",
190
+ "parse",
191
+ "parseInt",
192
+ "parseFloat",
193
+ "isInteger",
194
+ "isFinite",
195
+ "isNaN",
196
+ "toFixed",
197
+ "toISOString",
129
198
  // Promise/Function members
130
- "then", "catch", "finally", "resolve", "reject", "all", "allSettled",
131
- "race", "any", "call", "apply", "bind",
199
+ "then",
200
+ "catch",
201
+ "finally",
202
+ "resolve",
203
+ "reject",
204
+ "all",
205
+ "allSettled",
206
+ "race",
207
+ "any",
208
+ "call",
209
+ "apply",
210
+ "bind",
132
211
  // JSON / global constructors & functions
133
- "JSON", "stringify", "Math", "Date", "Promise", "Array", "Object", "String",
134
- "Number", "Boolean", "Symbol", "RegExp", "Error", "TypeError", "RangeError",
135
- "Map", "Set", "WeakMap", "WeakSet", "Buffer", "URL", "URLSearchParams",
136
- "isArray", "from", "of", "assign", "freeze", "create", "getOwnPropertyNames",
137
- "fromEntries", "setTimeout", "setInterval", "clearTimeout", "clearInterval",
138
- "queueMicrotask", "structuredClone", "fetch", "console", "process",
139
- "require", "encodeURIComponent", "decodeURIComponent", "encodeURI",
140
- "decodeURI", "atob", "btoa",
212
+ "JSON",
213
+ "stringify",
214
+ "Math",
215
+ "Date",
216
+ "Promise",
217
+ "Array",
218
+ "Object",
219
+ "String",
220
+ "Number",
221
+ "Boolean",
222
+ "Symbol",
223
+ "RegExp",
224
+ "Error",
225
+ "TypeError",
226
+ "RangeError",
227
+ "Map",
228
+ "Set",
229
+ "WeakMap",
230
+ "WeakSet",
231
+ "Buffer",
232
+ "URL",
233
+ "URLSearchParams",
234
+ "isArray",
235
+ "from",
236
+ "of",
237
+ "assign",
238
+ "freeze",
239
+ "create",
240
+ "getOwnPropertyNames",
241
+ "fromEntries",
242
+ "setTimeout",
243
+ "setInterval",
244
+ "clearTimeout",
245
+ "clearInterval",
246
+ "queueMicrotask",
247
+ "structuredClone",
248
+ "fetch",
249
+ "console",
250
+ "process",
251
+ "require",
252
+ "encodeURIComponent",
253
+ "decodeURIComponent",
254
+ "encodeURI",
255
+ "decodeURI",
256
+ "atob",
257
+ "btoa",
141
258
  // console members
142
- "warn", "info", "debug", "trace", "table", "dir", "group", "groupEnd",
143
- "assert", "time", "timeEnd",
259
+ "warn",
260
+ "info",
261
+ "debug",
262
+ "trace",
263
+ "table",
264
+ "dir",
265
+ "group",
266
+ "groupEnd",
267
+ "assert",
268
+ "time",
269
+ "timeEnd",
144
270
  ]);
145
271
  /** True when an UNRESOLVED callee name is a known JS/TS builtin. */
146
272
  function isBuiltinCallee(name) {
@@ -46,10 +46,10 @@ exports.ProjectBatchProcessor = void 0;
46
46
  const fs = __importStar(require("node:fs"));
47
47
  const path = __importStar(require("node:path"));
48
48
  const config_1 = require("../../config");
49
+ const vector_db_1 = require("../store/vector-db");
49
50
  const cache_check_1 = require("../utils/cache-check");
50
51
  const file_utils_1 = require("../utils/file-utils");
51
52
  const logger_1 = require("../utils/logger");
52
- const vector_db_1 = require("../store/vector-db");
53
53
  const pool_1 = require("../workers/pool");
54
54
  const watcher_batch_1 = require("./watcher-batch");
55
55
  // Fast path-segment check to reject events that leak through FSEvents overflow.
@@ -164,7 +164,8 @@ class ProjectBatchProcessor {
164
164
  break;
165
165
  attempted.add(absPath);
166
166
  processed++;
167
- if (batch.size > 10 && (processed % 10 === 0 || processed === batch.size)) {
167
+ if (batch.size > 10 &&
168
+ (processed % 10 === 0 || processed === batch.size)) {
168
169
  (0, logger_1.log)(this.wtag, `Progress: ${processed}/${batch.size} (${reindexed} reindexed)`);
169
170
  }
170
171
  if (event === "unlink") {
@@ -184,7 +185,7 @@ class ProjectBatchProcessor {
184
185
  }
185
186
  // Fast path: if only mtime changed but size matches and we have a hash,
186
187
  // verify in-process instead of dispatching to a worker (~220ms saved).
187
- if (cached && cached.hash && cached.size === stats.size) {
188
+ if ((cached === null || cached === void 0 ? void 0 : cached.hash) && cached.size === stats.size) {
188
189
  const buf = yield fs.promises.readFile(absPath);
189
190
  const hash = (0, file_utils_1.computeBufferHash)(buf);
190
191
  if (hash === cached.hash) {
@@ -319,8 +320,8 @@ class ProjectBatchProcessor {
319
320
  }
320
321
  }
321
322
  if (dropped > 0) {
322
- const droppedPaths = [...batch.keys()].filter(p => !requeued.has(p));
323
- (0, logger_1.log)(this.wtag, `Dropped ${dropped} file(s) after ${MAX_RETRIES} retries: ${droppedPaths.map(p => path.basename(p)).join(", ")}`);
323
+ const droppedPaths = [...batch.keys()].filter((p) => !requeued.has(p));
324
+ (0, logger_1.log)(this.wtag, `Dropped ${dropped} file(s) after ${MAX_RETRIES} retries: ${droppedPaths.map((p) => path.basename(p)).join(", ")}`);
324
325
  }
325
326
  backoffOverrideMs = this.pending.size > 0 ? backoffMs : 0;
326
327
  }
@@ -256,6 +256,7 @@ class TreeSitterChunker {
256
256
  if (c.definedSymbols && c.content.length > 100) {
257
257
  const extra = [];
258
258
  let m;
259
+ // biome-ignore lint/suspicious/noAssignInExpressions: idiomatic regex exec loop
259
260
  while ((m = PROP_FN_RE.exec(c.content)) !== null) {
260
261
  const name = m[1];
261
262
  if (name.length > 1 && !c.definedSymbols.includes(name)) {
@@ -278,6 +279,7 @@ class TreeSitterChunker {
278
279
  const existing = new Set(c.referencedSymbols);
279
280
  let jm;
280
281
  const jsxRefs = [];
282
+ // biome-ignore lint/suspicious/noAssignInExpressions: idiomatic regex exec loop
281
283
  while ((jm = JSX_RE.exec(c.content)) !== null) {
282
284
  // Extract base component name (e.g., "Foo" from "Foo.Bar")
283
285
  const full = jm[1];
@@ -55,11 +55,11 @@ exports.initialSync = initialSync;
55
55
  const fs = __importStar(require("node:fs"));
56
56
  const path = __importStar(require("node:path"));
57
57
  const config_1 = require("../../config");
58
- const logger_1 = require("../utils/logger");
59
58
  const meta_cache_1 = require("../store/meta-cache");
60
59
  const vector_db_1 = require("../store/vector-db");
61
60
  // isIndexableFile no longer used — extension check inlined for performance
62
61
  const lock_1 = require("../utils/lock");
62
+ const logger_1 = require("../utils/logger");
63
63
  const project_root_1 = require("../utils/project-root");
64
64
  const pool_1 = require("../workers/pool");
65
65
  const index_config_1 = require("./index-config");
@@ -173,7 +173,8 @@ function initialSync(options) {
173
173
  }
174
174
  projectKeys.clear();
175
175
  }
176
- else if (projectKeys.size > 0 && vectorFileCount < projectKeys.size * 0.8) {
176
+ else if (projectKeys.size > 0 &&
177
+ vectorFileCount < projectKeys.size * 0.8) {
177
178
  (0, logger_1.log)("index", `Partial cache detected: ${vectorFileCount} files in vectors vs ${projectKeys.size} in cache — clearing cache to re-embed missing files`);
178
179
  for (const key of projectKeys) {
179
180
  mc.delete(key);
@@ -351,13 +352,13 @@ function initialSync(options) {
351
352
  return; // Broken symlink
352
353
  }
353
354
  }
354
- if (!stats.isFile() || stats.size === 0 || stats.size > config_1.MAX_FILE_SIZE_BYTES) {
355
+ if (!stats.isFile() ||
356
+ stats.size === 0 ||
357
+ stats.size > config_1.MAX_FILE_SIZE_BYTES) {
355
358
  return;
356
359
  }
357
360
  // Use absolute path as the key for MetaCache
358
- const cached = treatAsEmptyCache
359
- ? undefined
360
- : mc.get(absPath);
361
+ const cached = treatAsEmptyCache ? undefined : mc.get(absPath);
361
362
  if (cached &&
362
363
  cached.mtimeMs === stats.mtimeMs &&
363
364
  cached.size === stats.size) {
@@ -11,14 +11,59 @@ const node_child_process_1 = require("node:child_process");
11
11
  exports.DIFF_MAX_LINES = 500;
12
12
  exports.SYMBOL_MAX = 10;
13
13
  const KEYWORD_SKIP = new Set([
14
- "public", "private", "internal", "protected", "open", "final", "static",
15
- "override", "class", "struct", "enum", "func", "function", "def", "const",
16
- "let", "var", "export", "async", "await", "import", "return", "if", "else",
17
- "for", "while", "switch", "case", "guard", "interface", "abstract", "sealed",
18
- "data", "suspend", "inline", "typealias", "extension", "protocol", "throws",
19
- "mutating", "nonmutating", "convenience", "required", "weak", "unowned",
20
- "lazy", "dynamic", "optional", "objc", "nonisolated", "isolated",
21
- "consuming", "borrowing",
14
+ "public",
15
+ "private",
16
+ "internal",
17
+ "protected",
18
+ "open",
19
+ "final",
20
+ "static",
21
+ "override",
22
+ "class",
23
+ "struct",
24
+ "enum",
25
+ "func",
26
+ "function",
27
+ "def",
28
+ "const",
29
+ "let",
30
+ "var",
31
+ "export",
32
+ "async",
33
+ "await",
34
+ "import",
35
+ "return",
36
+ "if",
37
+ "else",
38
+ "for",
39
+ "while",
40
+ "switch",
41
+ "case",
42
+ "guard",
43
+ "interface",
44
+ "abstract",
45
+ "sealed",
46
+ "data",
47
+ "suspend",
48
+ "inline",
49
+ "typealias",
50
+ "extension",
51
+ "protocol",
52
+ "throws",
53
+ "mutating",
54
+ "nonmutating",
55
+ "convenience",
56
+ "required",
57
+ "weak",
58
+ "unowned",
59
+ "lazy",
60
+ "dynamic",
61
+ "optional",
62
+ "objc",
63
+ "nonisolated",
64
+ "isolated",
65
+ "consuming",
66
+ "borrowing",
22
67
  ]);
23
68
  const DECL_RE = /(?:function|class|struct|enum|interface|func|def)\s+([a-zA-Z_][a-zA-Z0-9_]*)/g;
24
69
  const IDENT_RE = /[a-zA-Z_][a-zA-Z0-9_]*/g;
@@ -122,6 +167,7 @@ function extractSymbols(diff) {
122
167
  const idents = [];
123
168
  let m;
124
169
  IDENT_RE.lastIndex = 0;
170
+ // biome-ignore lint/suspicious/noAssignInExpressions: idiomatic regex exec loop
125
171
  while ((m = IDENT_RE.exec(ctx)) !== null) {
126
172
  if (!KEYWORD_SKIP.has(m[0]))
127
173
  idents.push(m[0]);
@@ -134,15 +180,14 @@ function extractSymbols(diff) {
134
180
  if (line.startsWith("+") && !line.startsWith("+++")) {
135
181
  DECL_RE.lastIndex = 0;
136
182
  let m;
183
+ // biome-ignore lint/suspicious/noAssignInExpressions: idiomatic regex exec loop
137
184
  while ((m = DECL_RE.exec(line)) !== null) {
138
185
  symbols.add(m[1]);
139
186
  }
140
187
  }
141
188
  }
142
189
  // Filter short identifiers and cap
143
- return [...symbols]
144
- .filter((s) => s.length >= 2)
145
- .slice(0, exports.SYMBOL_MAX);
190
+ return [...symbols].filter((s) => s.length >= 2).slice(0, exports.SYMBOL_MAX);
146
191
  }
147
192
  /**
148
193
  * Detect languages from file extensions.
@@ -56,9 +56,7 @@ const config_1 = require("./config");
56
56
  const prompts_1 = require("./prompts");
57
57
  const tools_1 = require("./tools");
58
58
  function stripThinkTags(text) {
59
- return text
60
- .replace(/<think(?:ing)?>[\s\S]*?<\/think(?:ing)?>/g, "")
61
- .trim();
59
+ return text.replace(/<think(?:ing)?>[\s\S]*?<\/think(?:ing)?>/g, "").trim();
62
60
  }
63
61
  function investigate(opts) {
64
62
  return __awaiter(this, void 0, void 0, function* () {
@@ -83,7 +81,12 @@ function investigate(opts) {
83
81
  const vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
84
82
  const searcher = new searcher_1.Searcher(vectorDb);
85
83
  const graphBuilder = new graph_builder_1.GraphBuilder(vectorDb, projectRoot);
86
- const ctx = { vectorDb, searcher, graphBuilder, projectRoot };
84
+ const ctx = {
85
+ vectorDb,
86
+ searcher,
87
+ graphBuilder,
88
+ projectRoot,
89
+ };
87
90
  const messages = [
88
91
  { role: "system", content: prompts_1.SYSTEM_PROMPT },
89
92
  { role: "user", content: question },
@@ -160,7 +163,11 @@ function investigate(opts) {
160
163
  if (verbose) {
161
164
  process.stderr.write(` ${fn.name}() — BLOCKED (limit)\n`);
162
165
  }
163
- messages.push({ role: "tool", tool_call_id: tc.id, content: result });
166
+ messages.push({
167
+ role: "tool",
168
+ tool_call_id: tc.id,
169
+ content: result,
170
+ });
164
171
  continue;
165
172
  }
166
173
  }
@@ -49,6 +49,7 @@ exports.reviewCommit = reviewCommit;
49
49
  const path = __importStar(require("node:path"));
50
50
  const openai_1 = __importDefault(require("openai"));
51
51
  const graph_builder_1 = require("../graph/graph-builder");
52
+ const risk_1 = require("../review/risk");
52
53
  const searcher_1 = require("../search/searcher");
53
54
  const vector_db_1 = require("../store/vector-db");
54
55
  const project_root_1 = require("../utils/project-root");
@@ -56,7 +57,6 @@ const config_1 = require("./config");
56
57
  const diff_1 = require("./diff");
57
58
  const report_1 = require("./report");
58
59
  const tools_1 = require("./tools");
59
- const risk_1 = require("../review/risk");
60
60
  function reviewCommit(opts) {
61
61
  return __awaiter(this, void 0, void 0, function* () {
62
62
  var _a, _b, _c, _d;
@@ -88,13 +88,21 @@ function reviewCommit(opts) {
88
88
  try {
89
89
  const searcher = new searcher_1.Searcher(vectorDb);
90
90
  const graphBuilder = new graph_builder_1.GraphBuilder(vectorDb, projectRoot);
91
- const ctx = { vectorDb, searcher, graphBuilder, projectRoot };
91
+ const ctx = {
92
+ vectorDb,
93
+ searcher,
94
+ graphBuilder,
95
+ projectRoot,
96
+ };
92
97
  // Deterministic risk ranking (Phase 8) — gives the LLM an explicit
93
98
  // blast-radius × tests × churn ordering to anchor its judgement, rather
94
99
  // than inferring importance from prose alone.
95
100
  const [context, riskInputs] = yield Promise.all([
96
101
  gatherContext(symbols, changedFiles, ctx, verbose),
97
- (0, risk_1.gatherRiskInputs)(commitRef, projectRoot, { vectorDb, graphBuilder }).catch(() => []),
102
+ (0, risk_1.gatherRiskInputs)(commitRef, projectRoot, {
103
+ vectorDb,
104
+ graphBuilder,
105
+ }).catch(() => []),
98
106
  ]);
99
107
  contextStr = context;
100
108
  const riskRows = (0, risk_1.computeRiskTable)(riskInputs);
@@ -202,7 +210,11 @@ function gatherContext(symbols, changedFiles, ctx, verbose) {
202
210
  if (s.status !== "fulfilled")
203
211
  continue;
204
212
  const { type, result } = s.value;
205
- if (result.startsWith("(") && (result.includes("not found") || result.includes("error") || result.includes("not indexed") || result.includes("none")))
213
+ if (result.startsWith("(") &&
214
+ (result.includes("not found") ||
215
+ result.includes("error") ||
216
+ result.includes("not indexed") ||
217
+ result.includes("none")))
206
218
  continue;
207
219
  if (type === "peek")
208
220
  peekResults.push(result);
@@ -356,12 +368,13 @@ ${diff}
356
368
  // Response parsing
357
369
  // ---------------------------------------------------------------------------
358
370
  function stripThinkTags(text) {
359
- return text
360
- .replace(/<think(?:ing)?>[\s\S]*?<\/think(?:ing)?>/g, "")
361
- .trim();
371
+ return text.replace(/<think(?:ing)?>[\s\S]*?<\/think(?:ing)?>/g, "").trim();
362
372
  }
363
373
  function parseFindings(content) {
364
- const empty = { findings: [], summary: "Parse error — could not extract findings from model output." };
374
+ const empty = {
375
+ findings: [],
376
+ summary: "Parse error — could not extract findings from model output.",
377
+ };
365
378
  if (!content)
366
379
  return empty;
367
380
  // Strip think tags and markdown fences
@@ -85,7 +85,9 @@ class LlmServer {
85
85
  const runningModel = (_b = (_a = body === null || body === void 0 ? void 0 : body.data) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.id;
86
86
  if (runningModel) {
87
87
  const configBasename = path.basename(this.config.model);
88
- if (runningModel !== configBasename && !configBasename.includes(runningModel) && !runningModel.includes(configBasename)) {
88
+ if (runningModel !== configBasename &&
89
+ !configBasename.includes(runningModel) &&
90
+ !runningModel.includes(configBasename)) {
89
91
  console.log(`[llm] Model mismatch: running "${runningModel}" but config expects "${configBasename}" — will restart`);
90
92
  resolve(false);
91
93
  return;
@@ -142,11 +144,16 @@ class LlmServer {
142
144
  }
143
145
  const logFd = (0, log_rotate_1.openRotatedLog)(config_1.PATHS.llmLogFile);
144
146
  const child = (0, node_child_process_1.spawn)(binary, [
145
- "-m", this.config.model,
146
- "--host", this.config.host,
147
- "--port", String(this.config.port),
148
- "-ngl", String(this.config.ngl),
149
- "--ctx-size", String(this.config.ctxSize),
147
+ "-m",
148
+ this.config.model,
149
+ "--host",
150
+ this.config.host,
151
+ "--port",
152
+ String(this.config.port),
153
+ "-ngl",
154
+ String(this.config.ngl),
155
+ "--ctx-size",
156
+ String(this.config.ctxSize),
150
157
  ], { detached: true, stdio: ["ignore", logFd, logFd] });
151
158
  child.unref();
152
159
  fs.closeSync(logFd);
@@ -256,7 +263,9 @@ class LlmServer {
256
263
  pid: alive ? pid : null,
257
264
  port: this.config.port,
258
265
  model: this.config.model,
259
- uptime: alive && this.startTime ? Math.floor((Date.now() - this.startTime) / 1000) : 0,
266
+ uptime: alive && this.startTime
267
+ ? Math.floor((Date.now() - this.startTime) / 1000)
268
+ : 0,
260
269
  };
261
270
  }
262
271
  startIdleWatchdog() {
@@ -102,9 +102,31 @@ function firstSignatureLine(chunk) {
102
102
  return "";
103
103
  }
104
104
  const QUERY_STOPWORDS = new Set([
105
- "the", "and", "for", "with", "that", "this", "from", "into", "where",
106
- "when", "how", "what", "does", "not", "are", "was", "has", "have", "its",
107
- "all", "can", "use", "uses", "using", "code",
105
+ "the",
106
+ "and",
107
+ "for",
108
+ "with",
109
+ "that",
110
+ "this",
111
+ "from",
112
+ "into",
113
+ "where",
114
+ "when",
115
+ "how",
116
+ "what",
117
+ "does",
118
+ "not",
119
+ "are",
120
+ "was",
121
+ "has",
122
+ "have",
123
+ "its",
124
+ "all",
125
+ "can",
126
+ "use",
127
+ "uses",
128
+ "using",
129
+ "code",
108
130
  ]);
109
131
  function extractQueryTerms(query) {
110
132
  if (!query)
@@ -14,7 +14,7 @@ exports.formatIndexStateFooter = formatIndexStateFooter;
14
14
  * while results may actually be incomplete.
15
15
  */
16
16
  function formatIndexStateFooter(state, opts) {
17
- if (!state || !state.indexing)
17
+ if (!(state === null || state === void 0 ? void 0 : state.indexing))
18
18
  return null;
19
19
  const count = state.pendingFiles > 0 ? `~${state.pendingFiles} files pending` : null;
20
20
  if (opts.agent) {
@@ -40,9 +40,7 @@ function computeRiskTable(inputs) {
40
40
  /** Render the ranking — TSV-ish for agents, an aligned table for humans. */
41
41
  function formatRiskTable(rows, opts) {
42
42
  if (rows.length === 0) {
43
- return opts.agent
44
- ? "(no changed symbols)"
45
- : "No changed symbols to rank.";
43
+ return opts.agent ? "(no changed symbols)" : "No changed symbols to rank.";
46
44
  }
47
45
  if (opts.agent) {
48
46
  return rows
@@ -70,7 +68,7 @@ function gatherRiskInputs(ref, projectRoot, deps) {
70
68
  if (symbols.length === 0)
71
69
  return [];
72
70
  const root = projectRoot.endsWith("/") ? projectRoot : `${projectRoot}/`;
73
- const relativize = (f) => (f.startsWith(root) ? f.slice(root.length) : f);
71
+ const relativize = (f) => f.startsWith(root) ? f.slice(root.length) : f;
74
72
  const inputs = yield Promise.all(symbols.map((symbol) => __awaiter(this, void 0, void 0, function* () {
75
73
  var _a, _b;
76
74
  const [callers, loc, tests] = yield Promise.all([