Skip to content

fix(recall): keep the trace id when the endpoint filters - #26

Merged
DottytheHomeless merged 1 commit into
mainfrom
fix/recall-trace-id-survives-filters
Aug 3, 2026
Merged

DottytheHomeless merged 1 commit into
mainfrom
fix/recall-trace-id-survives-filters

Conversation

@MXAntian

@MXAntian MXAntian commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

The bug

/recall answers trace_id: null on every filtered call — which is every call any real caller makes.

recallTrace rides on the returned array as a non-enumerable property, and Array.prototype.filter builds a new array. Reading it after min_importance / level / require_vec yields undefined.

Measured against a live server before the fix:

no filters      trace_id = "7defe884-7ecf-4a54-85d1-6e4c0c94e291"
min_importance  trace_id = null
hook-shaped     trace_id = null

Both hooks send min_importance and level on every call, so the id was present only in the unfiltered case nobody uses.

Why it stayed quiet

The trace is persisted either way. recall_traces fills with rows no caller can name — from inside the DB the instrumentation looks healthy.

The consequence is that the citation contract only has a first half. Every recall ships:

<memory-citation-contract trace-id="…" allowed-ids="…">
Only cite [id:N] values listed in allowed-ids. Validate generated citations
against this trace before publishing.
</memory-citation-contract>

…and then get_recall_trace / validate_memory_references have nothing to be called with, because the caller that would call them never received an id.

Fix

Capture the trace before the filters instead of after.

Test

Asserts the id survives min_importance, level, and the exact shape both hooks send. Without the fix those three go red while the unfiltered case still passes — that asymmetry is what hid it:

✗ trace id survives min_importance — trace_id=null hits=2
✗ trace id survives level — trace_id=null hits=2
✗ trace id survives the shape both hooks send — trace_id=null hits=2

Full suite: 284 passed / 0 failed.

🤖 Generated with Claude Code

/recall answered trace_id: null on every filtered call, which is every call
any real caller makes.

recallTrace rides on the returned array as a non-enumerable property, and
Array.prototype.filter builds a new array. Reading it after min_importance /
level / require_vec yields undefined. Measured against a live server before
the fix:

  no filters      trace_id = "7defe884-7ecf-4a54-85d1-6e4c0c94e291"
  min_importance  trace_id = null
  hook-shaped     trace_id = null

Both hooks send min_importance and level on every call, so the id was present
only in the unfiltered case nobody uses.

What made it quiet is that the trace was persisted either way. recall_traces
fills up with rows no caller can name — the data looks healthy from inside the
DB, and get_recall_trace / validate_memory_references have nothing to be called
with, so the citation contract's second half cannot run at all. The first half
ships in every recall: allowed-ids and "validate generated citations against
this trace before publishing."

Fix is to capture the trace before the filters rather than after. Test asserts
the id survives min_importance, level, and the exact shape both hooks send;
without the fix those three go red and the unfiltered case still passes, which
is the asymmetry that hid it.

284 passed / 0 failed.

Co-authored-by: 千夏 <qianxia@clawgamers.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@MXAntian
MXAntian marked this pull request as ready for review August 3, 2026 19:11
@DottytheHomeless
DottytheHomeless merged commit 75a170e into main Aug 3, 2026
2 checks passed
@DottytheHomeless
DottytheHomeless deleted the fix/recall-trace-id-survives-filters branch August 3, 2026 19:12
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.

2 participants