Skip to content

fix: resolve vec0 chunk excerpts via batch content lookup #192 - #193

Merged
four-bytes-robby merged 3 commits into
mainfrom
fix/192-vec0-chunk-excerpt
Jun 29, 2026
Merged

fix: resolve vec0 chunk excerpts via batch content lookup #192#193
four-bytes-robby merged 3 commits into
mainfrom
fix/192-vec0-chunk-excerpt

Conversation

@four-bytes-robby

@four-bytes-robby four-bytes-robby commented Jun 29, 2026

Copy link
Copy Markdown
Member

Closes #192

Problem

searchVec0() in src/search/unified.ts queried only chunks_vec (chunk_id + distance) and returned placeholder excerpts like [vec0 chunk] distance=13.3280 with opaque vec0:<uuid> titles. Users got no meaningful content from vec0 search results.

Fix

After the KNN query returns chunk_id + distance, a batch SELECT ... FROM chunks JOIN documents WHERE id IN (...) resolves all chunk IDs in one query. The results are mapped to a Map<chunk_id, chunk> for efficient lookup.

  • excerpt: Real content (truncated to 80 chars, matching the fallback path in searchChunksFallback)
  • title: symbol ?? ${doc_title}:${chunk_type}#${chunk_index}`` (same as fallback path)
  • source_path, metadata (kind, chunk_type, start_line, end_line): Now populated identically to fallback path
  • Fallback: If a chunk_id somehow doesn't exist in the chunks table, the old placeholder format is used as a safety net

Version

1.8.1 → 1.8.2 (patch bump)

Testing

  • Build verified: bun run build passes cleanly
  • The vec0 results now have the same content quality as searchChunksFallback and FTS5 results

Summary by cubic

Fixes vec0 search results by resolving chunk IDs to real content via a batched lookup with safe limits. Results now show real titles, concise excerpts, and full metadata to match fallback and FTS5 results.

  • Bug Fixes
    • Batch-lookup chunk data for all vec0 KNN hits (JOIN documents) and map by ID.
    • Clamp both fetch and mapping to a 500-ID window; truncate excerpts to 80 chars with ellipsis.
    • Populate title, source_path, and metadata; fallback to placeholders if a chunk is missing.

Written for commit a5faf9e. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Search results now show richer details, including better titles, real content excerpts, and additional context like section type and line range.
    • Search entries now include more source information, making results easier to understand and navigate.
  • Chores

    • Updated the package version to 1.8.2.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/192-vec0-chunk-excerpt
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/192-vec0-chunk-excerpt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/search/unified.ts`:
- Around line 371-374: The vec0 excerpt formatting in unified search is
exceeding the 80-character contract because it slices to 80 and then appends an
ellipsis. Update the excerpt logic in the unified search path around the
chunk.content truncation so the final returned string never exceeds 80
characters, including any suffix, while preserving the existing excerpt
behavior.
- Around line 334-343: Cap the vec0 post-lookup in searchVec0 to avoid
generating an oversized WHERE c.id IN (...) clause from a caller-provided
options.limit. Update the chunkIds/chunkRows lookup logic in unified.ts to
either clamp the effective limit to a safe ceiling before building placeholders
or batch the chunkIds into multiple queries, so db.query does not hit SQLite
host-parameter limits and fall back to an empty result set.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b3ccdeb8-c96d-4352-ab8d-2b1c1a787698

📥 Commits

Reviewing files that changed from the base of the PR and between 50b4167 and 80ae0af.

📒 Files selected for processing (2)
  • package.json
  • src/search/unified.ts

Comment thread src/search/unified.ts Outdated
Comment thread src/search/unified.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/search/unified.ts">

<violation number="1" location="src/search/unified.ts:342">
P2: Vec0 content lookup still ignores search filters. Apply `mergedFilters` to the vec0 chunk resolution path (or pass filters into `searchVec0`) so filtered searches do not return unrelated chunks.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/search/unified.ts
c.chunk_index, c.kind, d.path AS source_path, d.title AS doc_title
FROM chunks c
JOIN documents d ON d.id = c.document_id
WHERE c.id IN (${placeholders})`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Vec0 content lookup still ignores search filters. Apply mergedFilters to the vec0 chunk resolution path (or pass filters into searchVec0) so filtered searches do not return unrelated chunks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/search/unified.ts, line 342:

<comment>Vec0 content lookup still ignores search filters. Apply `mergedFilters` to the vec0 chunk resolution path (or pass filters into `searchVec0`) so filtered searches do not return unrelated chunks.</comment>

<file context>
@@ -328,13 +328,67 @@ async function searchVec0(
+                c.chunk_index, c.kind, d.path AS source_path, d.title AS doc_title
+         FROM chunks c
+         JOIN documents d ON d.id = c.document_id
+         WHERE c.id IN (${placeholders})`,
+      )
+      .all(...chunkIds) as Array<{
</file context>

Comment thread src/search/unified.ts Outdated
@four-bytes-robby

Copy link
Copy Markdown
Member Author

@coderabbitai Fixed both actionable comments in 550e96d:

  1. Excerpt length cap: slice(0, 80) + "..."slice(0, 77) + "..." — total now 80 chars
  2. Chunk ID clamp: Added MAX_BATCH_IDS = 500 safety ceiling with rows.slice(0, MAX_BATCH_IDS) before building WHERE c.id IN (...) clause

@cubic-dev-ai

Issue #1 (clamp): Fixed in 550e96d — added MAX_BATCH_IDS = 500 ceiling with explanatory comment.

Issue #2 (filters): Won't fix in this PR. This is a pre-existing architectural gap — searchVec0() has never applied mergedFilters (even before our change, vec0 results were placeholder excerpts with no filter awareness). The FTS5 paths handle filtering; vec0 returns semantic neighbors which are inherently content-type agnostic. Adding filter propagation to the vec0 path is a feature-level change that warrants its own issue with design discussion (tradeoffs: performance cost of JOIN-based filtering vs. post-retrieval filtering).

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 29, 2026

Copy link
Copy Markdown

@coderabbitai Fixed both actionable comments in 550e96d:

  1. Excerpt length cap: slice(0, 80) + "..."slice(0, 77) + "..." — total now 80 chars
  2. Chunk ID clamp: Added MAX_BATCH_IDS = 500 safety ceiling with rows.slice(0, MAX_BATCH_IDS) before building WHERE c.id IN (...) clause

...

@four-bytes-robby Looks good on both fronts.

Excerpt clampslice(0, 77) + "..." produces exactly 80 chars total. Clean fix.

Batch ID clampMAX_BATCH_IDS = 500 with rows.slice(0, MAX_BATCH_IDS) before the IN (...) clause. That's a sensible SQLite safety ceiling.

Filters — Your reasoning makes sense. searchVec0() has never applied mergedFilters, and this PR is about content resolution, not adding filter capability. Semantic search + filtering is a design decision with real tradeoffs (JOIN cost, embedding drift from filtered subsets, post-filtering recall vs. pre-filtering). A separate issue with a concrete design discussion is the right call.

Tip: get faster answers by chatting with cubic’s review copilot in the review UI

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@four-bytes-robby Thanks for the update — the two actionable fixes sound good, and the scope call on the mergedFilters gap in src/search/unified.ts makes sense for this PR.

If you want, I can also open a follow-up GitHub issue for the deferred vec0 filter propagation work so it’s tracked separately.


✏️ Learnings added
Learnt from: four-bytes-robby
URL: https://github.com/four-bytes/four-opencode-brain/pull/193

Timestamp: 2026-06-29T21:41:29.975Z
Learning: In `src/search/unified.ts`, `searchVec0()` does not currently apply `mergedFilters`; this is a pre-existing architectural gap. The FTS5 search paths handle filtering, while vec0 returns semantic neighbors in a content-type-agnostic way, so adding filter propagation is considered a feature-level change that should be handled in a separate issue/PR with design discussion.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/search/unified.ts">

<violation number="1" location="src/search/unified.ts:342">
P2: Vec0 content lookup still ignores search filters. Apply `mergedFilters` to the vec0 chunk resolution path (or pass filters into `searchVec0`) so filtered searches do not return unrelated chunks.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/search/unified.ts
@four-bytes-robby

Copy link
Copy Markdown
Member Author

@cubic-dev-ai Good catch. Fixed in a5faf9e: changed rows.map(...)rows.slice(0, MAX_BATCH_IDS).map(...) so the iteration window matches the batch fetch window exactly.

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 29, 2026

Copy link
Copy Markdown

@cubic-dev-ai Good catch. Fixed in a5faf9e: changed rows.map(...)rows.slice(0, MAX_BATCH_IDS).map(...) so the iteration window matches the batch fetch window exactly.

@four-bytes-robby Looks correct. Both the batch query and the iteration now share the same rows.slice(0, MAX_BATCH_IDS) window, so you can't end up iterating over more rows than you fetched content for. Consistent and safe.

Tip: get faster answers by chatting with cubic’s review copilot in the review UI

@four-bytes-robby
four-bytes-robby merged commit 265af70 into main Jun 29, 2026
5 checks passed
@four-bytes-robby
four-bytes-robby deleted the fix/192-vec0-chunk-excerpt branch June 29, 2026 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIX] brain_search vec0 chunk results show placeholder excerpts instead of real content

1 participant