Skip to content

fix: dedupe chunks across queries in a multi-query ctx_search call#921

Open
uwuclxdy wants to merge 1 commit into
mksglu:nextfrom
uwuclxdy:fix/timeline-cross-query-dedup
Open

fix: dedupe chunks across queries in a multi-query ctx_search call#921
uwuclxdy wants to merge 1 commit into
mksglu:nextfrom
uwuclxdy:fix/timeline-cross-query-dedup

Conversation

@uwuclxdy

@uwuclxdy uwuclxdy commented Jul 5, 2026

Copy link
Copy Markdown

What / Why / How

Root cause: ctx_search runs each query in queryList independently and pushes a ## ${q} section per query, with no state shared across the loop. A chunk that matches more than one query is printed verbatim under every matching query's section, spending context on duplicates.

Fix: dedupe chunks across the call's queries with a shared Set that keeps the first occurrence. It lives in a small exported helper, dedupeAcrossQueries, so tests can hit it directly. Neither SearchResult nor UnifiedSearchResult has a stable chunk id. The key is therefore the query-independent source + title + content tuple; the per-query snippet cannot serve, because extractSnippet windows it around each query's terms. Single-query output stays byte-identical: the dedup only runs when queryList.length > 1. A later query whose matches were all shown earlier now reads (all matches already shown above).

Affected platforms

  • Claude Code
  • Cursor
  • VS Code Copilot (GitHub Copilot)
  • JetBrains Copilot
  • Gemini CLI
  • Qwen Code
  • OpenCode
  • KiloCode
  • Codex CLI
  • OpenClaw (Pi Agent)
  • Pi
  • Kiro
  • Antigravity
  • Zed
  • All platforms

Test plan

  • npx tsc -b --noEmit clean.
  • npx vitest run tests/core/search.test.ts green. Added ctx_search cross-query dedup, covering: a chunk matching two queries is emitted once with the first occurrence kept, and distinct chunks that share source and title are not falsely deduped.

Checklist

  • Tests added/updated (TDD: red → green)
  • npm test passes
  • npm run typecheck passes
  • Docs updated if needed (README, platform-support.md)
  • No Windows path regressions (forward slashes only)
  • Targets next branch (unless hotfix)
Cross-platform notes

Our CI runs on Ubuntu, macOS, and Windows.

  • If touching file paths, verify forward-slash normalization on Windows
  • If touching hook paths, verify no backslash separators
  • Use path.join() / path.resolve(), never hardcode / separators
  • Use event-based stdin reading — readFileSync(0) breaks on Windows
  • Use os.tmpdir(), never hardcode /tmp

A chunk matching more than one query was printed verbatim under each query's
section because no state was shared across the query loop. Track emitted
chunks across the call's queries and keep only the first occurrence, so a
chunk matching several queries appears once. Only multi-query calls change;
single-query output stays byte-identical. When a later query's matches were
all shown already, its section reads `(all matches already shown above)`.
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.

1 participant