Skip to content

fix: memory_recall includeFullText now returns L2 content instead of L0#334

Merged
rwmjhb merged 3 commits intoCortexReach:masterfrom
lamkacheong:fix/memory-recall-full-text-returns-l2
Mar 27, 2026
Merged

fix: memory_recall includeFullText now returns L2 content instead of L0#334
rwmjhb merged 3 commits intoCortexReach:masterfrom
lamkacheong:fix/memory-recall-full-text-returns-l2

Conversation

@lamkacheong
Copy link
Contributor

Closes #333

Problem

memory_recall with includeFullText: true was returning L0 (one-line abstract) instead of the full L2 content. This happened because the text column in LanceDB stores the L0 abstract, and the tool read directly from that column for both includeFullText: true and false — making the parameter a no-op.

// Before (broken)
const base = includeFullText
  ? r.entry.text            // ← r.entry.text is L0
  : metadata.l0_abstract || r.entry.text;

Fix

Resolve full content through the L2 → L1 → L0 fallback chain when includeFullText: true:

// After
const base = includeFullText
  ? (metadata.l2_content || metadata.l1_overview || r.entry.text)
  : (metadata.l0_abstract || r.entry.text);

Also add fullText to sanitizeMemoryForSerialization so the details.memories structured payload exposes L2 content for callers that inspect the tool response directly.

Why this matters

When an agent explicitly calls memory_recall, it signals active intent to retrieve memory detail. Auto-recall (passive injection) returning L0 hints is fine — it keeps context concise. But an explicit tool call should return the full narrative, especially for cases and patterns categories where L2 contains actionable step-by-step content that L0 cannot capture in one line.

Changes

  • src/tools.ts — 2 hunks, no new dependencies

When an agent explicitly calls memory_recall with includeFullText: true,
it signals active intent to retrieve detailed memory content. Previously
this still returned r.entry.text (which stores the L0 abstract), making
includeFullText a no-op.

Fix: resolve full content via L2 → L1 → L0 fallback chain so agents
get the complete narrative when they ask for it. Also expose fullText
in sanitizeMemoryForSerialization so the details.memories payload
carries L2 content for callers that inspect the structured response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@AliceLJY
Copy link
Collaborator

确认了这个 bug 在 beta.10 上依然存在,tools.ts 里 includeFullText 确实还是返回 L0 的 text。fix 方向正确,保持 text 不变 + 加 fullText 字段,向后兼容。

麻烦 rebase 到最新 master,然后补一个 tool 级回归测试:验证 rendered output 和 details.memories[].fullText 都拿到的是 L2 内容。

rebase + 补测试后可以合 👍

Verify that passing includeFullText:true to memory_recall returns L2
content (not the L0 abstract) in both the rendered text output and
details.memories[].fullText. Also asserts that details.memories[].text
still carries L0 for backwards compatibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lamkacheong
Copy link
Contributor Author

lamkacheong commented Mar 24, 2026

已完成!rebase 到最新 master,并在 test/recall-text-cleanup.test.mjs 补了回归测试。

新增测试(includeFullText=true renders L2 content in output, not L0 abstract)覆盖了你要求的两个验证点:

  • 验证 rendered text 行包含 L2 内容,而非 L0 摘要
  • 验证 details.memories[0].fullText 等于 L2 内容
  • 顺带断言 details.memories[0].text 仍保留 L0,向后兼容

16 个测试全部通过,可以合了 🙏

@AliceLJY
Copy link
Collaborator

感谢补测试和 rebase,修复方向没问题。代码层面有两个点需要调整:

1. fullText 暴露范围过大

sanitizeMemoryForSerialization 是共享 helper,memory_forgetmemory_updatememory_explain_rank 等工具都在调。把 fullText 加在这里意味着所有工具都会无条件返回 L2 全文,包括 includeFullText=false 的场景——违背了 opt-in 的设计意图,也会让不需要全文的响应体膨胀。

建议:fullText 不要动 sanitizeMemoryForSerialization,改为仅在 memory_recall handler 内、includeFullText=true 时注入到 details.memories 里。

2. 补两个测试

  • includeFullText=falsedetails.memories[].fullText 应该是 undefined(验证 opt-in 边界)
  • legacy 记忆(metadata 里没有 l2_content / l1_overview)的 fallback 行为——确认最终拿到的是 r.entry.text

这两个改完再看 🙏

…ests

Move fullText injection out of sanitizeMemoryForSerialization (shared
helper used by all tools) and into the memory_recall execute handler,
injected only when includeFullText=true. This keeps the opt-in contract
clean and avoids L2 content bloating responses from other tools.

Add two regression tests:
- includeFullText=false: details.memories[].fullText is undefined
- legacy memory (no smart metadata): fullText falls back to entry.text

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lamkacheong
Copy link
Contributor Author

两个问题都改好了:

1. fullText 收回到 memory_recall handler 内
sanitizeMemoryForSerialization 已恢复原样,fullText 只在 memory_recall execute handler 里、includeFullText=true 时才注入到 details.memories,不影响其他工具。

2. 补了两个测试

  • includeFullText=falsedetails.memories[].fullTextundefined(验证 opt-in 边界)
  • 没有 smart metadata 的 legacy 记忆,fullText fallback 到 entry.text

18 个测试全部通过 🙏

@AliceLJY AliceLJY requested a review from rwmjhb March 25, 2026 17:49
@AliceLJY
Copy link
Collaborator

@rwmjhb 恒哥看一下这个 PR,作者已经改了两轮,我这边 review 过了觉得可以,你确认下能不能合 👀

@rwmjhb rwmjhb merged commit da8f042 into CortexReach:master Mar 27, 2026
2 of 3 checks passed
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.

bug: memory_recall with includeFullText:true still returns L0 abstract instead of full content

3 participants