grepmax 0.17.17 → 0.17.18

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.
@@ -621,16 +621,25 @@ class Searcher {
621
621
  const FUSED_WEIGHT = Number.isFinite(envBlend) && envBlend >= 0 ? envBlend : 0.5;
622
622
  if (queryPooled && topCandidates.length > STAGE2_K) {
623
623
  const cosineScores = topCandidates.map((doc) => {
624
- if (!doc.pooled_colbert_48d)
624
+ const docVec = doc.pooled_colbert_48d;
625
+ // Reject missing or short vectors. Also treat an all-zero vector as
626
+ // "no pooled signal" rather than a genuine cosine of 0 — chunks indexed
627
+ // before the pooled-IPC fix (orchestrator.ts) stored all-zero padding,
628
+ // and on a mixed index those must sort below chunks that carry real
629
+ // pooled vectors, not tie with orthogonal ones.
630
+ if (!docVec || docVec.length < queryPooled.length)
625
631
  return -1;
626
632
  // Manual cosine sim since we don't have helper here easily
627
633
  // Assuming vectors are normalized (which they should be from orchestrator)
628
634
  let dot = 0;
629
- const docVec = doc.pooled_colbert_48d;
635
+ let nonZero = false;
630
636
  for (let i = 0; i < queryPooled.length; i++) {
631
- dot += queryPooled[i] * (docVec[i] || 0);
637
+ const c = docVec[i] || 0;
638
+ if (c !== 0)
639
+ nonZero = true;
640
+ dot += queryPooled[i] * c;
632
641
  }
633
- return dot;
642
+ return nonZero ? dot : -1;
634
643
  });
635
644
  // Sort by cosine score and keep top N
636
645
  const withScore = topCandidates.map((doc, i) => ({
@@ -287,7 +287,15 @@ class WorkerOrchestrator {
287
287
  colbert: new Int8Array(),
288
288
  scale: 1,
289
289
  };
290
- return Object.assign(Object.assign({}, chunk), { vector: hybrid.dense, colbert: Buffer.from(hybrid.colbert), colbert_scale: hybrid.scale, pooled_colbert_48d: hybrid.pooled_colbert_48d, doc_token_ids: hybrid.token_ids });
290
+ return Object.assign(Object.assign({}, chunk), { vector: hybrid.dense, colbert: Buffer.from(hybrid.colbert), colbert_scale: hybrid.scale,
291
+ // Convert the pooled Float32Array to a plain number[] so it survives
292
+ // the JSON IPC hop to the parent (process-child.ts → pool.ts). A typed
293
+ // array JSON-serializes to a length-less {"0":..} object, which then
294
+ // Array.from()s to [] on insert and pads to 48 zeros — silently making
295
+ // the stage-1 cosine prefilter a no-op (searcher.ts:732).
296
+ pooled_colbert_48d: hybrid.pooled_colbert_48d
297
+ ? Array.from(hybrid.pooled_colbert_48d)
298
+ : undefined, doc_token_ids: hybrid.token_ids });
291
299
  });
292
300
  onProgress === null || onProgress === void 0 ? void 0 : onProgress();
293
301
  (0, logger_1.debug)("orch", `processFile done: ${input.path} ${vectors.length} vectors ${(performance.now() - fileStart).toFixed(0)}ms`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.17.17",
3
+ "version": "0.17.18",
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.17.17",
3
+ "version": "0.17.18",
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",