Skip to content

fix(memory): use per-keyword FTS search in hybrid mode #39484#73976

Merged
vincentkoc merged 1 commit into
mainfrom
clownfish/ghcrawl-156988-autonomous-smoke
Jun 16, 2026
Merged

fix(memory): use per-keyword FTS search in hybrid mode #39484#73976
vincentkoc merged 1 commit into
mainfrom
clownfish/ghcrawl-156988-autonomous-smoke

Conversation

@openclaw-clownfish

Copy link
Copy Markdown
Contributor

Canonical repair path for #39555. Before merge, rebase or refresh the contributor branch against main 79159f1 if needed, verify the bounded per-keyword hybrid FTS fan-out remains narrow, rerun Codex /review and address every finding, then run pnpm check:changed. This preserves @yangzi33's source PR credit and keeps the existing changelog attribution.

ProjectClownfish replacement details:

@openclaw-clownfish openclaw-clownfish Bot added the clawsweeper Tracked by ClawSweeper automation label Apr 29, 2026
@openclaw-barnacle openclaw-barnacle Bot added extensions: memory-core Extension: memory-core size: S r: too-many-prs Auto-close: author has more than twenty active PRs. labels Apr 29, 2026
@openclaw-barnacle

Copy link
Copy Markdown

Closing this PR because the author has more than 10 active PRs in this repo. Please reduce the active PR queue and reopen or resubmit once it is back under the limit. You can close your own PRs to get back under the limit.

@greptile-apps

greptile-apps Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refactors the per-keyword FTS fallback for hybrid memory search into a dedicated searchKeywordWithFallback method, capping fan-out at KEYWORD_FALLBACK_SEARCH_TERM_LIMIT = 6 to prevent unbounded SQLite work on long prompts. Two previously skipped tests are re-enabled and a new bounding test is added. The pre-existing relaxedMinScore = 0 concern (noted in a prior review comment outside the diff) remains unaddressed.

Confidence Score: 5/5

Safe to merge; no new P1/P0 issues introduced by this PR.

All findings are P2. The structural refactor is clean and the fan-out cap is correctly enforced. The relaxedMinScore = 0 concern was flagged in a prior review. Only a minor test-reliability observation remains.

No files require special attention beyond the pre-existing relaxedMinScore = 0 concern in manager.ts.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/memory-core/src/memory/index.test.ts
Line: 420-436

Comment:
**`db.prepare` spy measures an implementation detail, not query executions**

The fan-out bound assertion relies on counting how many times `db.prepare(sql)` is called with an FTS SQL pattern. If `searchKeyword` (or its underlying helper) ever starts caching prepared statements — a natural performance improvement for `better-sqlite3` — the same `Statement` object is reused across invocations without calling `prepare` again. In that case `ftsSelects` stays at 1 even when 7 queries actually execute, making `expect(ftsSelects).toBeGreaterThan(1)` a false failure and `expect(ftsSelects).toBeLessThanOrEqual(7)` trivially true. Spying on a lower-level execution hook (`.all` / `.get` on the prepared statement) or using an integration assertion (e.g. counting distinct results per term) would be more durable.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (2): Last reviewed commit: "fix(memory): use per-keyword FTS search ..." | Re-trigger Greptile

Comment thread extensions/memory-core/src/memory/manager.ts Outdated
@vincentkoc vincentkoc reopened this Apr 29, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the r: too-many-prs Auto-close: author has more than twenty active PRs. label Apr 29, 2026
@clawsweeper

clawsweeper Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed June 15, 2026, 2:37 AM ET / 06:37 UTC.

Summary
This PR refactors memory-core hybrid search to use a bounded per-keyword FTS fallback, re-enables/adds memory search tests, and adds a changelog entry.

PR surface: Source +29, Tests +40, Docs +1. Total +70 across 3 files.

Reproducibility: yes. at source level, but I did not execute tests in this read-only review. Current main and v2026.6.6 still run only the full AND-joined keyword query in provider-backed hybrid mode, while related reports show indexed terms missed until per-keyword lexical broadening is used.

Review metrics: 2 noteworthy metrics.

  • FTS fallback fan-out cap: 6 terms. The cap is the key guard against unbounded SQLite MATCH work when long prompts trigger per-keyword fallback probes.
  • Release-owned changelog edit: 1 added entry. Normal PRs should not edit CHANGELOG.md, so this must be removed before merge.

Stored data model
Persistent data-model change detected: unknown-data-model-change: extensions/memory-core/src/memory/index.test.ts, unknown-data-model-change: extensions/memory-core/src/memory/manager.ts, vector/embedding metadata: extensions/memory-core/src/memory/index.test.ts, vector/embedding metadata: extensions/memory-core/src/memory/manager.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🌊 off-meta tidepool
Patch quality: 🦐 gold shrimp
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Port or replace the branch against current main.
  • Remove the CHANGELOG.md edit while preserving release-note context outside the release-owned file.
  • Run targeted memory-core search validation after the port.

Risk before merge

  • [P1] GitHub reports this PR as CONFLICTING/DIRTY, so maintainers need a current-main port or replacement branch before trusting the final merge result.
  • [P2] The fallback broadens provider-backed lexical recall for memory and session chunks, which can change which persisted context enters agent responses; ranking, temporal decay, MMR, boostFallbackRanking, and fan-out behavior need focused validation after the port.
  • [P1] The branch edits release-owned CHANGELOG.md and should drop that file while preserving release-note context in the PR body or squash message.
  • [P1] A newer open memory selection PR at fix(memory-core): preserve keyword-only hybrid results #92524 touches the same manager area, so the port should integrate with that selection boundary if it lands first.

Maintainer options:

  1. Port The Bounded Fallback On Current Main (recommended)
    Refresh or replace the branch so the helper applies to the current manager search path, removes the changelog edit, and preserves current ranking and selection semantics.
  2. Accept Retrieval Semantics After Proof
    Maintainers may accept the broader lexical recall behavior if focused validation shows the returned memory/session context is ranked and capped as intended.
  3. Pause For Memory Scoring Coordination
    If maintainers want fix(memory-core): preserve keyword-only hybrid results #92524 or broader memory-scoring policy to land first, pause this PR and rebase the fallback afterward.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Rebase or replace this PR against current main; remove the CHANGELOG.md edit; implement bounded per-keyword FTS fallback for provider-backed hybrid memory search without changing current temporal-decay, boostFallbackRanking, relaxed keyword-hit, or MMR semantics; account for https://github.com/openclaw/openclaw/pull/92524 if it has landed; add focused regression coverage for provider-backed split multi-word recall and long-query fan-out bounds; run targeted memory-core validation.

Next step before merge

  • [P2] The remaining action is a concrete repair: refresh the useful fallback onto current main, remove the release-owned changelog edit, and validate the memory-core search path.

Security
Cleared: The diff is limited to memory search logic, colocated tests, and changelog text; I found no dependency, workflow, secret, permission, install, or supply-chain surface change.

Review findings

  • [P3] Remove the release-owned changelog edit — CHANGELOG.md:62
Review details

Best possible solution:

Port the bounded provider-backed per-keyword FTS fallback onto current main, integrate cleanly with the current hybrid selection code, drop the changelog edit, and validate memory-core recall/fan-out behavior before merge.

Do we have a high-confidence way to reproduce the issue?

Yes at source level, but I did not execute tests in this read-only review. Current main and v2026.6.6 still run only the full AND-joined keyword query in provider-backed hybrid mode, while related reports show indexed terms missed until per-keyword lexical broadening is used.

Is this the best way to solve the issue?

Yes in direction, but not as submitted. The bounded fallback belongs in memory-core's manager path, but this branch needs a current-main port, changelog removal, and focused ranking/fan-out validation before it is the best mergeable fix.

Full review comments:

  • [P3] Remove the release-owned changelog edit — CHANGELOG.md:62
    This PR adds a normal fix entry to CHANGELOG.md, but repository policy keeps the changelog release-generated for normal PRs. Keep the release-note context in the PR body or squash message and drop this file from the branch before merge.
    Confidence: 0.93

Overall correctness: patch is correct
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against bcb016a528b1.

Label changes

Label justifications:

  • P2: This is a bounded memory recall bug fix with real user impact but no crash, security bypass, or data-loss emergency.
  • merge-risk: 🚨 session-state: Changing provider-backed hybrid recall can change which persisted memories or session transcript chunks are supplied to agent context.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🌊 off-meta tidepool and patch quality is 🦐 gold shrimp.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: Not applicable: this is a bot-created replacement PR carrying a maintainer repair path, so the external contributor proof gate is not applied; current-main validation is still needed before merge.
Evidence reviewed

PR surface:

Source +29, Tests +40, Docs +1. Total +70 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 1 73 44 +29
Tests 1 42 2 +40
Docs 1 1 0 +1
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 116 46 +70

Acceptance criteria:

  • [P2] node scripts/run-vitest.mjs extensions/memory-core/src/memory/index.test.ts -t "hybrid search|keyword|FTS fallback|fan-out|keyword-only".
  • [P1] node scripts/run-vitest.mjs extensions/memory-core/src/memory/manager-search.test.ts.
  • [P1] node scripts/run-vitest.mjs extensions/memory-core/src/memory/hybrid.test.ts.
  • [P1] node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions/memory-core/src/memory/manager.ts extensions/memory-core/src/memory/index.test.ts.
  • [P1] git diff --check -- extensions/memory-core/src/memory/manager.ts extensions/memory-core/src/memory/index.test.ts.

What I checked:

Likely related people:

  • vincentkoc: Authored the latest commit on this PR, authored the bounded per-keyword hybrid FTS repair commit in the source history, and appears in current-main blame for the inspected manager search block. (role: recent area contributor and branch repair author; confidence: high; commits: 610b9c2292c4, 8ad671b64b9c, 10b0dea77af0; files: extensions/memory-core/src/memory/manager.ts, extensions/memory-core/src/memory/index.test.ts)
  • yangzi33: Opened the original source PR with the multi-word zero-hit reproduction and authored the initial per-keyword hybrid FTS change carried forward here. (role: original source contributor; confidence: high; commits: a39adae822ca, b0c9d7155de6; files: extensions/memory-core/src/memory/manager.ts, extensions/memory-core/src/memory/index.test.ts)
  • opriz: Merged history for fix(memory): populate FTS index when no embedding provider is configured #56473 added FTS-only memory search behavior and default-threshold handling, the sibling fallback path this PR mirrors. (role: adjacent FTS-only feature contributor; confidence: medium; commits: 41c30f0c5901, 677e84c98c9b, 8fbf84fb5ade; files: extensions/memory-core/src/memory/manager.ts, extensions/memory-core/src/memory/index.test.ts)
  • AnonAmit: Authored the merged fallback lexical-ranking PR that changed searchKeyword scoring behavior used by this fallback path. (role: adjacent ranking contributor; confidence: medium; commits: 42590106ab6e, 1c20b1416cd4, 15064ec0bde6; files: extensions/memory-core/src/memory/manager-search.ts, extensions/memory-core/src/memory/manager.ts)
  • Vignesh Natarajan: Commit f57b466 added the hybrid keyword-hit preservation behavior that current main still carries near this search boundary. (role: introduced adjacent fallback behavior; confidence: medium; commits: f57b4669e1d6; files: src/memory/manager.ts, src/memory/index.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label May 30, 2026
@clawsweeper clawsweeper Bot added the rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. label May 30, 2026
@barnacle-openclaw barnacle-openclaw Bot removed the stale Marked as stale due to inactivity label May 30, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Jun 14, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 14, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Jun 15, 2026
@vincentkoc
vincentkoc force-pushed the clownfish/ghcrawl-156988-autonomous-smoke branch from 610b9c2 to df43337 Compare June 16, 2026 06:24
@vincentkoc vincentkoc added the clownfish Tracked by Clownfish automation label Jun 16, 2026
@vincentkoc
vincentkoc merged commit e1d3f12 into main Jun 16, 2026
22 of 24 checks passed
@vincentkoc
vincentkoc deleted the clownfish/ghcrawl-156988-autonomous-smoke branch June 16, 2026 06:25
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 17, 2026
…openclaw#73976)

Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
crh-code pushed a commit to crh-code/openclaw that referenced this pull request Jun 18, 2026
…openclaw#73976)

Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clawsweeper Tracked by ClawSweeper automation clownfish Tracked by Clownfish automation extensions: memory-core Extension: memory-core merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant