Skip to content

fix: skip applyRecencyBoost when decayEngine is active in vectorOnlyRetrieval#500

Open
jlin53882 wants to merge 2 commits intoCortexReach:masterfrom
jlin53882:fix/recency-double-boost-guard-v2
Open

fix: skip applyRecencyBoost when decayEngine is active in vectorOnlyRetrieval#500
jlin53882 wants to merge 2 commits intoCortexReach:masterfrom
jlin53882:fix/recency-double-boost-guard-v2

Conversation

@jlin53882
Copy link
Copy Markdown
Contributor

@jlin53882 jlin53882 commented Apr 4, 2026

Summary

Skip applyRecencyBoost in vectorOnlyRetrieval() when a decayEngine is present, preventing double-counting of recency in the scoring pipeline.

What was fixed

Problem: vectorOnlyRetrieval() always called this.applyRecencyBoost(mapped), but when a decayEngine is active, the applyDecayBoost() stage already incorporates recency into its composite score. Calling both created a double-boost on recency, distorting ranking.

Fix: Guard applyRecencyBoost with a ternary ??if this.decayEngine exists, use mapped directly; otherwise call this.applyRecencyBoost(mapped).

Files changed

  • src/retriever.ts: +5/-1 lines in vectorOnlyRetrieval()

Testing

  • Only affects vector-only retrieval path when decayEngine is configured
  • Hybrid retrieval path already handles this correctly

Related

…ieval

Bug 7 fix: when decayEngine is active, skip applyRecencyBoost here because
decayEngine already handles temporal scoring; avoid double-boost.
@rwmjhb
Copy link
Copy Markdown
Collaborator

rwmjhb commented Apr 4, 2026

Review: fix: skip applyRecencyBoost when decayEngine is active in vectorOnlyRetrieval

Correct fix — hybrid and BM25 paths already skip legacy recency when decayEngine is active, vector-only was the remaining inconsistency.

Must Fix

No regression test for the fixed behavior. The vector-only + decayEngine branch is not exercised by any existing test. Add one.

Worth noting

Skipping recency boost before hardMinScore cutoff means recent memories that start below the floor can be discarded before applyDecayBoost() has a chance to lift them. This reduces recall in edge cases — consider applying decay boost before the hard cutoff, or document this as an accepted trade-off.

…ine active in vectorOnlyRetrieval

Co-authored-by: Review Claw <review-claw@openclaw.ai>
@jlin53882
Copy link
Copy Markdown
Contributor Author

Reviewer Must Fix: ✅ 已處理

迴攻測試已加入: est/retriever-decay-recency-double-boost.mjs

包含 3 個測試案例:

  1. 驗證有 decayEngine 時不會套用 double-boost
  2. 驗證分數在合理範圍(ratio 0.3-3.0),確認無 double-boost bug
  3. bm25-only path 與 vector path 的一致性檢查

深層分析額外發現(NIT,不阻擋 merge)

等級 問題 說明
[MINOR] hardMinScore 文件不符 docstring 說「after all scoring stages」,實際在 time decay 之前
[NIT] vectorOnlyRetrieval 缺少 recency trace 與 bm25/hybrid path 不一致
[NIT] afterImportance 診斷在 decay path 無意義 與 afterRecency 值相同

PR 核心 fix 正確,無 blocking 問題。

Copy link
Copy Markdown
Collaborator

@AliceLJY AliceLJY left a comment

Choose a reason for hiding this comment

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

Fix is correct and well-scoped. The guard this.decayEngine ? mapped : this.applyRecencyBoost(mapped) is consistent with the hybrid path pattern and prevents double-boosting. Test coverage is adequate.

CI cli-smoke failure is pre-existing on master (strip-envelope-metadata tests), unrelated to this PR.

Approved.

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.

3 participants