Skip to content

feat(memory-core): expose vectorScore and textScore in hybrid search results#68286

Merged
BunsDev merged 2 commits intoopenclaw:mainfrom
ajfonthemove:feat/memory-search-component-scores
Apr 25, 2026
Merged

feat(memory-core): expose vectorScore and textScore in hybrid search results#68286
BunsDev merged 2 commits intoopenclaw:mainfrom
ajfonthemove:feat/memory-search-component-scores

Conversation

@ajfonthemove
Copy link
Copy Markdown
Contributor

Summary

  • Problem: mergeHybridResults computes vectorScore and textScore per
    result but drops them when building the return object. Only the
    weighted combined score survives.
  • Why it matters: operators running multi-agent setups need to compare
    retrieval quality across embedding models and weight configs. The
    combined score hides which component drove the ranking.
  • What changed: two fields (vectorScore, textScore) now pass through
    the merge result in hybrid.ts. MemorySearchResult in memory-host-sdk
    adds them as optional fields.
  • What did NOT change: scoring math, temporal decay, MMR re-ranking,
    minScore filtering. The combined score field stays the primary
    ranking signal.

Change Type

  • Feature

Scope

  • Memory / storage
  • API / contracts

Linked Issue/PR

Root Cause

N/A

Regression Test Plan

  • Coverage level:
    • Unit test
  • Target test: extensions/memory-core/src/memory/hybrid.test.ts
  • Scenario: existing mergeHybridResults tests now assert vectorScore
    and textScore on each result. Disjoint ids (one component is 0)
    and overlapping ids (both contribute).
  • Why smallest reliable: the merge function is pure. Unit tests cover
    the full branch space; no live gateway required.
  • Existing test that already covers this: hybrid.test.ts covered the
    combined score; six new assertions extend those same tests.

User-visible / Behavior Changes

  • MemorySearchResult adds optional vectorScore and textScore fields.
  • memory_search results include component scores when hybrid search
    is active. Consumers that don't read these fields see no difference.

Diagram

N/A

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Ubuntu 24.04 (Linux 6.14)
  • Runtime: Node 22.22.0, pnpm 10.32.1
  • Model/provider: N/A (unit tests only)

Steps

  1. pnpm install
  2. node scripts/test-extension.mjs memory-core

Expected

hybrid.test.ts passes with vectorScore/textScore assertions.

Actual

46 passed, 1 pre-existing failure (dreaming-phases fixture paths,
unrelated, same on main).

Evidence

  • Failing test/log before + passing after

Human Verification

  • Verified: full memory-core suite (47 files, 431 tests passing).
  • Edge cases: overlapping ids, disjoint ids, keyword-only results.
  • Not verified: live gateway end-to-end with a real embedding provider.

Review Conversations

  • N/A -- initial submission.

Compatibility / Migration

  • Backward compatible? Yes, new fields are optional.
  • Config/env changes? No
  • Migration needed? No

Disclosure

Claude Code helped me straighten out my word salad for this PR.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 17, 2026

Greptile Summary

Exposes vectorScore and textScore on hybrid search results so multi-agent operators can compare retrieval quality across embedding models and weight configs. Both component scores pass through correctly: applyTemporalDecayToHybridResults uses spread-plus-override (only score changes), and applyMMRToHybridResults returns the original typed objects by reference, so neither post-processing step drops the new fields. Both MemorySearchResult type files (src/memory-host-sdk and packages/memory-host-sdk) are updated consistently with optional fields, preserving backward compatibility.

Confidence Score: 5/5

Safe to merge — purely additive, backward compatible, no scoring logic changed.

All remaining feedback is P2 (a doc/comment suggestion about temporal decay semantics). The implementation is correct: component scores flow through both post-processing stages and are typed consistently across the two SDK type files. No data loss, no ranking regressions.

No files require special attention.

Comments Outside Diff (1)

  1. extensions/memory-core/src/memory/hybrid.ts, line 143-150 (link)

    P2 Component scores not adjusted by temporal decay

    After applyTemporalDecayToHybridResults, score is multiplied by the decay factor but vectorScore and textScore retain their pre-decay values, so vectorWeight * vectorScore + textWeight * textScore ≠ score when decay is active. This is arguably the right design (raw retrieval quality vs. age-adjusted ranking signal), but a short comment here would prevent consumers from silently computing an incorrect "reconstructed" combined score.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: extensions/memory-core/src/memory/hybrid.ts
    Line: 143-150
    
    Comment:
    **Component scores not adjusted by temporal decay**
    
    After `applyTemporalDecayToHybridResults`, `score` is multiplied by the decay factor but `vectorScore` and `textScore` retain their pre-decay values, so `vectorWeight * vectorScore + textWeight * textScore ≠ score` when decay is active. This is arguably the right design (raw retrieval quality vs. age-adjusted ranking signal), but a short comment here would prevent consumers from silently computing an incorrect "reconstructed" combined score.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/memory-core/src/memory/hybrid.ts
Line: 143-150

Comment:
**Component scores not adjusted by temporal decay**

After `applyTemporalDecayToHybridResults`, `score` is multiplied by the decay factor but `vectorScore` and `textScore` retain their pre-decay values, so `vectorWeight * vectorScore + textWeight * textScore ≠ score` when decay is active. This is arguably the right design (raw retrieval quality vs. age-adjusted ranking signal), but a short comment here would prevent consumers from silently computing an incorrect "reconstructed" combined score.

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

Reviews (1): Last reviewed commit: "feat(memory-core): expose vectorScore an..." | Re-trigger Greptile

@prtags
Copy link
Copy Markdown

prtags Bot commented Apr 23, 2026

Related work from PRtags group trusted-ibex-o48x

Title: Open PR duplicate: [Feature]: expose vectorScore and textScore in hybrid search results

Number Title
#68286* feat(memory-core): expose vectorScore and textScore in hybrid search results
#68830 fix(memory): expose vectorScore and textScore in hybrid search results

* This PR

ajfonthemove and others added 2 commits April 25, 2026 01:40
…results

mergeHybridResults computes both component scores per result but
drops them when building the return object. This carries them through
so callers can see the score breakdown.

Closes openclaw#68166
@BunsDev BunsDev force-pushed the feat/memory-search-component-scores branch from e507814 to 2ca5fe4 Compare April 25, 2026 06:42
@BunsDev
Copy link
Copy Markdown
Member

BunsDev commented Apr 25, 2026

Maintainer update before landing:

  • Rebased onto current main.
  • Added the requested note that vectorScore and textScore are raw retrieval diagnostics, while temporal decay/MMR only adjust or reorder the combined score.

Local verification:

  • pnpm test extensions/memory-core/src/memory/hybrid.test.ts
  • pnpm check:changed

Waiting for fresh GitHub checks before merge.

@BunsDev BunsDev merged commit 66e66f1 into openclaw:main Apr 25, 2026
64 checks passed
vincentkoc added a commit that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for #66884 that
restated alexlomt's already-formatted entry one line above.
steipete pushed a commit to MonkeyLeeT/openclaw that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
Angfr95 pushed a commit to Angfr95/openclaw that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
ayesha-aziz123 pushed a commit to ayesha-aziz123/openclaw that referenced this pull request Apr 26, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: expose vectorScore and textScore in hybrid search results

3 participants