grepmax 0.26.14 → 0.26.15

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.
@@ -10,7 +10,7 @@
10
10
  "name": "grepmax",
11
11
  "source": "./plugins/grepmax",
12
12
  "description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
13
- "version": "0.26.14",
13
+ "version": "0.26.15",
14
14
  "author": {
15
15
  "name": "Robert Owens",
16
16
  "email": "robowens@me.com"
@@ -324,9 +324,13 @@ function initialSync(options) {
324
324
  yield currentFlush;
325
325
  (0, logger_1.debug)("index", `flush done: ${Date.now() - flushStart}ms`);
326
326
  flushCount++;
327
- // Periodically compact during sync to prevent fragment accumulation
327
+ // Periodically compact during sync to prevent fragment accumulation.
328
+ // Uses the shared threshold deliberately: a hardcoded 30 here meant
329
+ // the full-index path kept compacting at the old rate long after the
330
+ // threshold was raised to 400, re-triggering the whole-table rewrite
331
+ // that raising it exists to avoid.
328
332
  if (flushCount % 10 === 0) {
329
- yield vectorDb.compactIfNeeded(30);
333
+ yield vectorDb.compactIfNeeded(config_1.FRAGMENT_COMPACT_THRESHOLD);
330
334
  }
331
335
  }
332
336
  catch (err) {
@@ -187,22 +187,115 @@ function isIndexableFile(filePath, size) {
187
187
  function isIndexablePath(filePath) {
188
188
  return isIndexableFile(filePath);
189
189
  }
190
- // Well-known machine-generated markers emitted at the top of codegen output.
191
- // Tools (protoc, graphql-codegen, Apollo, Relay, Go `stringer`, OpenAPI, etc.)
192
- // stamp one of these in a banner comment. Matched against only the first few KB
193
- // because the banner is always at the very top — this keeps a hand-written
194
- // "do not edit this section" note deep in a real file from being misclassified.
195
- const GENERATED_MARKER = /@generated\b|\bDO NOT EDIT\b|Code generated by |auto-?generated by |This (?:file|code) (?:is|was) (?:\w+[ -])?generated|machine generated|@autogenerated\b/i;
190
+ // Markers that only ever appear in a codegen banner. Any one of these, on its
191
+ // own, is enough. Tools (protoc, graphql-codegen, Apollo, Relay, Go `stringer`,
192
+ // OpenAPI) stamp one of these; doc generators fence their output with the
193
+ // `generated-body` / `AUTO-GENERATED-CONTENT` style directives.
194
+ const STRONG_GENERATED_MARKER = /@generated\b|@autogenerated\b|\bCode generated by |\bauto-?generated by |\bThis (?:file|code) (?:is|was) (?:\w+[ -])?generated|\bmachine[ -]generated\b|\bauto-?generated[-_ ]?content\b|\bgenerated[-_](?:body|content|section|block)\b|\bBEGIN GENERATED\b/i;
195
+ // "DO NOT EDIT" is not proof of codegen on its own — humans write it on prose
196
+ // they want left alone (archived vendor snapshots, verbatim captures). Real
197
+ // codegen banners pair it with a generation word, so require that pairing.
198
+ const DO_NOT_EDIT_MARKER = /\bDO NOT EDIT\b/i;
199
+ const GENERATION_CONTEXT = /generat|codegen|autogen/i;
196
200
  const GENERATED_SNIFF_BYTES = 2048;
201
+ const DOC_LIKE_EXTENSIONS = /\.(?:md|mdx|markdown|txt|rst|adoc|asciidoc)$/i;
202
+ /**
203
+ * Extract the leading banner: the run of shebang, frontmatter, blank, and
204
+ * comment lines at the very top, stopping at the first line of actual code.
205
+ *
206
+ * Scanning raw head bytes instead was the bug this replaces. Two ways it
207
+ * misfired, both silently erasing hand-written files from the index:
208
+ *
209
+ * - A *generator* was classified as its own output, because the banner it
210
+ * emits appears as a string literal in its body
211
+ * (`lines.push('# Auto-generated by ...')`).
212
+ * - A comment quoting another file's rules ("its README says do not edit")
213
+ * counted as a banner.
214
+ *
215
+ * A real codegen banner precedes all code, so anchoring here removes both
216
+ * without weakening detection.
217
+ *
218
+ * In doc-like files `#` starts a heading, not a comment, so only frontmatter
219
+ * and HTML comments count — otherwise the whole document body would be read as
220
+ * banner.
221
+ */
222
+ function leadingBanner(head, filePath) {
223
+ var _a, _b;
224
+ const docLike = filePath ? DOC_LIKE_EXTENSIONS.test(filePath) : false;
225
+ const lines = head.split("\n");
226
+ const banner = [];
227
+ let i = 0;
228
+ if (!docLike && ((_a = lines[0]) === null || _a === void 0 ? void 0 : _a.startsWith("#!"))) {
229
+ banner.push(lines[0]);
230
+ i = 1;
231
+ }
232
+ // YAML frontmatter is metadata, not code — a generated-doc marker often sits
233
+ // directly after it.
234
+ if (((_b = lines[i]) === null || _b === void 0 ? void 0 : _b.trim()) === "---") {
235
+ banner.push(lines[i]);
236
+ i++;
237
+ while (i < lines.length && lines[i].trim() !== "---")
238
+ banner.push(lines[i++]);
239
+ if (i < lines.length)
240
+ banner.push(lines[i++]);
241
+ }
242
+ let blockEnd;
243
+ for (; i < lines.length; i++) {
244
+ const line = lines[i];
245
+ const trimmed = line.trim();
246
+ if (blockEnd) {
247
+ banner.push(line);
248
+ if (trimmed.includes(blockEnd))
249
+ blockEnd = undefined;
250
+ continue;
251
+ }
252
+ if (trimmed === "") {
253
+ banner.push(line);
254
+ continue;
255
+ }
256
+ if (trimmed.startsWith("<!--")) {
257
+ banner.push(line);
258
+ if (!trimmed.includes("-->"))
259
+ blockEnd = "-->";
260
+ continue;
261
+ }
262
+ if (!docLike) {
263
+ if (trimmed.startsWith("/*")) {
264
+ banner.push(line);
265
+ if (!trimmed.includes("*/"))
266
+ blockEnd = "*/";
267
+ continue;
268
+ }
269
+ if (trimmed.startsWith("//") ||
270
+ trimmed.startsWith("#") ||
271
+ trimmed.startsWith("--") ||
272
+ trimmed.startsWith(";") ||
273
+ trimmed.startsWith("*")) {
274
+ banner.push(line);
275
+ continue;
276
+ }
277
+ }
278
+ break; // first real line of content — the banner is over
279
+ }
280
+ return banner.join("\n");
281
+ }
197
282
  /**
198
283
  * Detect machine-generated source by its banner. Generated files flood both the
199
284
  * vector index and the symbol graph (codegen types rank as god nodes), so they
200
285
  * are skipped at index time. Path globs in `ignore-patterns.ts` catch the
201
286
  * obvious filenames; this catches the rest by content.
287
+ *
288
+ * `filePath` is optional but worth passing: without it, doc-like files are
289
+ * scanned with code comment rules, so a markdown `# Heading` reads as a comment.
202
290
  */
203
- function isGeneratedContent(buffer) {
291
+ function isGeneratedContent(buffer, filePath) {
204
292
  const head = buffer.subarray(0, GENERATED_SNIFF_BYTES).toString("utf-8");
205
- return GENERATED_MARKER.test(head);
293
+ const banner = leadingBanner(head, filePath);
294
+ if (!banner.trim())
295
+ return false;
296
+ if (STRONG_GENERATED_MARKER.test(banner))
297
+ return true;
298
+ return DO_NOT_EDIT_MARKER.test(banner) && GENERATION_CONTEXT.test(banner);
206
299
  }
207
300
  function formatDenseSnippet(text, maxLength = 1500) {
208
301
  const clean = text !== null && text !== void 0 ? text : "";
@@ -256,7 +256,7 @@ class WorkerOrchestrator {
256
256
  (0, logger_1.debug)("orch", `skip ${input.path} (empty or binary)`);
257
257
  return { vectors: [], hash, mtimeMs, size, shouldDelete: true };
258
258
  }
259
- if ((0, file_utils_1.isGeneratedContent)(buffer)) {
259
+ if ((0, file_utils_1.isGeneratedContent)(buffer, absolutePath)) {
260
260
  (0, logger_1.debug)("orch", `skip ${input.path} (machine-generated header)`);
261
261
  return { vectors: [], hash, mtimeMs, size, shouldDelete: true };
262
262
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.26.14",
3
+ "version": "0.26.15",
4
4
  "author": "Robert Owens <78518764+reowens@users.noreply.github.com>",
5
5
  "homepage": "https://github.com/reowens/grepmax",
6
6
  "bugs": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.26.14",
3
+ "version": "0.26.15",
4
4
  "description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
5
5
  "author": {
6
6
  "name": "Robert Owens",