Skip to content

fix: preserve temporal embeddings on distillation + expose source IDs in recall#380

Merged
BYK merged 1 commit into
mainfrom
fix-recall-expansion
May 19, 2026
Merged

fix: preserve temporal embeddings on distillation + expose source IDs in recall#380
BYK merged 1 commit into
mainfrom
fix-recall-expansion

Conversation

@BYK
Copy link
Copy Markdown
Owner

@BYK BYK commented May 19, 2026

Summary

Two surgical changes to improve recall's ability to surface specific details from prior sessions.

Problem

When a temporal message is distilled, markDistilled() sets distilled=1 AND embedding=NULL. This makes the original message invisible to vector search — the only way to find 'bcrypt with 12 salt rounds' is if the distillation preserved it (which it often doesn't).

Additionally, when recall returns a distillation hit, the LLM has no way to access the original messages that were distilled — it only sees the compressed summary.

Changes

1. Preserve embeddings on markDistilled()

Changed UPDATE temporal_messages SET distilled = 1, embedding = NULL to just SET distilled = 1. The embedding is kept so vector search can still find the original message when the query matches its semantic content. BM25/LIKE searches still filter on distilled=0 (unchanged) to avoid result dilution.

2. Source message IDs in distillation recall results

Distillation results now include (sources: t:id1, t:id2, ...) — the IDs of the temporal messages that were distilled into this segment. The existing recallById() function already handles t:<id> lookups, so the LLM can fetch full message content when the summary lacks specifics.

Files Changed

  • packages/core/src/temporal.ts — stop NULLing embedding in markDistilled()
  • packages/core/src/recall.tsgetDistillationSourceIds() + source refs in distillation rendering

… in recall

Two changes to improve recall detail availability:

1. Stop NULLing embeddings on markDistilled() — distilled temporal
   messages remain findable via vector search, preserving the semantic
   search path for specific details the distillation may have dropped.

2. Distillation results in recall now include source message IDs
   (t:<id> format). The LLM can use these with the recall tool to
   fetch full message content when the distilled summary lacks
   specifics (algorithm names, config values, file paths, etc.).
@BYK BYK self-assigned this May 19, 2026
@BYK BYK merged commit ed7c794 into main May 19, 2026
10 checks passed
@BYK BYK deleted the fix-recall-expansion branch May 19, 2026 08:20
BYK added a commit that referenced this pull request May 19, 2026
## Summary

Fixes a bug where preserved temporal message embeddings were never used
because the vector search query still excluded distilled messages.

## Problem

PR #380 stopped NULLing embeddings on `markDistilled()` specifically to
keep temporal messages findable via vector search. But
`vectorSearchTemporal()` in `embedding.ts` still had `AND distilled = 0`
in the SQL query — making the preserved embeddings dead data.

## Fix

Remove `distilled = 0` from `vectorSearchTemporal()` only. BM25/LIKE
search paths keep the filter (preventing keyword-match duplication with
distillations). Only vector search is opened up — this provides the
semantic similarity path for finding specific details in distilled
messages.

## Results

PR-2 at 400K tokens:

| Baseline | Before | After |
|---|---|---|
| **Lore** | 4.20 | **4.68** |
| Tail-window | 2.90 | 2.65 |

Per-question improvements:
- Tests alongside implementation: 2.6 → **4.6**
- Error handling expectations: 4.0 → **5.0**

## Files Changed
- `packages/core/src/embedding.ts` — remove `distilled = 0` from
`vectorSearchTemporal()`
This was referenced May 21, 2026
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