Skip to content

feat: expose graph edge metadata (caused_by, leads_to, timestamp) in memory_search - #301

Open
xDarkicex wants to merge 3 commits into
mainfrom
feat/expose-graph-edges-in-search
Open

feat: expose graph edge metadata (caused_by, leads_to, timestamp) in memory_search#301
xDarkicex wants to merge 3 commits into
mainfrom
feat/expose-graph-edges-in-search

Conversation

@xDarkicex

@xDarkicex xDarkicex commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Surface causal graph edge metadata from metadataJson in memory_search results
  • why_idscaused_by (upstream causal parents — "from")
  • how_idsleads_to (downstream procedural children — "to")
  • tstimestamp (ISO 8601, human-readable)
  • Also exposes memory_kind and memory_signals in structured result path (was only in legacy path)

No daemon changes required — data already flows through metadataJson, just wasn't surfaced in tool output.

Test plan

  • Verify memory_search returns caused_by/leads_to arrays on records with graph edges
  • Verify memory_search returns timestamp on records with ts metadata
  • Verify memory_kind and memory_signals appear in structured results
  • Verify legacy path returns same fields

Summary by CodeRabbit

  • New Features
    • Memory search results now show enriched metadata: kind, signals, causal links (what caused / what leads to), and normalized timestamps for clearer context.
  • Documentation
    • Help/description for the memory search tool updated to document the new fields and clarify usage guidance.

Surface causal graph edges (why_ids → caused_by, how_ids → leads_to)
and timestamps from record metadata in both legacy and structured search
result paths. This enables agents to traverse the event DAG for causal
reasoning without new RPCs — the data was already flowing through
metadataJson, just not surfaced in tool output.

Also exposes memory_kind and memory_signals in structured results for
consistency with the legacy path.
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

src/memory-runtime.ts enriches memory search results with metadata fields. Legacy result mapping and the toMemorySearchResult function now conditionally attach kind, signals, caused_by, leads_to, and timestamp by parsing stored metadata. Helper functions extract string arrays and normalize timestamps into ISO format.

Changes

Memory Search Result Metadata Enrichment

Layer / File(s) Summary
Search result metadata enrichment
src/memory-runtime.ts
Legacy search results and non-legacy toMemorySearchResult outputs are enriched with parsed metadata fields (kind from memory_kind, signals from memory_signals, caused_by from why_ids, leads_to from how_ids, and timestamp parsed from multiple timestamp-like metadata keys). Helper functions extract string arrays from metadata and normalize timestamps into ISO strings.
Tool description update
src/memory-tools.ts
memory_search tool description expanded to document the new result metadata fields (kind, signals, caused_by, leads_to, timestamp) and retain usage guidance about calling once per question and disabled=true handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

release:patch

Poem

🐰 In burrows of bytes I hop and pry,

I gather the signals that whisper why.
I stitch timestamps and causes in line,
So memories glow, arranged and fine.
Hooray — enriched traces, neat and spry!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: exposing graph edge metadata (caused_by, leads_to, timestamp) in memory_search results. It is specific, clear, and directly relates to the primary objective of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/expose-graph-edges-in-search

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/memory-runtime.ts`:
- Around line 351-359: The metaTimestamp function can call
Date.prototype.toISOString() on a Date that is invalid or out-of-range which may
throw; update metaTimestamp to validate the constructed Date (e.g., const d =
new Date(ts); check Number.isFinite(d.getTime()) and d.getTime() >
-Infinity/…/not NaN) and/or wrap the toISOString() call in a try/catch and
return undefined on failure so a single bad metadata.ts does not throw; apply
this change to the metaTimestamp function to ensure numeric and parsed string
timestamps are converted safely and invalid/out-of-range dates are treated as
“no timestamp.”
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ab3eb1a2-6202-4cbc-bb10-8f1f62cdfd71

📥 Commits

Reviewing files that changed from the base of the PR and between 944bbbd and 00b85dc.

📒 Files selected for processing (1)
  • src/memory-runtime.ts

Comment thread src/memory-runtime.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/memory-tools.ts (1)

199-205: ⚡ Quick win

Keep the local result type aligned with the documented fields.

This description now advertises kind, signals, caused_by, leads_to, and timestamp, but MemorySearchResult on Lines 34-42 still only models the old fields. Updating the type here will keep the tool contract self-consistent and prevent future code in this file from accidentally ignoring the new metadata.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/memory-tools.ts` around lines 199 - 205, Update the MemorySearchResult
type to include the newly documented metadata fields so the local type matches
the tool contract: add optional properties kind (string), signals (number or
appropriate enum/bitmask type used elsewhere), caused_by (string[]), leads_to
(string[]), and timestamp (string, ISO 8601) to the MemorySearchResult
interface/type definition; ensure any references to MemorySearchResult (e.g.,
functions that deserialize search results) accept and preserve these fields and
adjust imports/types if a shared enum/type (for signals) exists.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/memory-tools.ts`:
- Around line 202-203: The doc text incorrectly instructs callers to pass event
IDs from caused_by/leads_to into memory_get; memory_get expects a path produced
by memory_search, not raw event IDs. Update the wording around the caused_by and
leads_to descriptions to either (a) tell callers to call memory_search with
those event IDs to obtain a path and then pass that path to memory_get, or (b)
say to use memory_get only with paths returned by memory_search and to use
memory_get/memory_search together to walk the causal chain; reference symbols:
caused_by, leads_to, memory_get, memory_search.

---

Nitpick comments:
In `@src/memory-tools.ts`:
- Around line 199-205: Update the MemorySearchResult type to include the newly
documented metadata fields so the local type matches the tool contract: add
optional properties kind (string), signals (number or appropriate enum/bitmask
type used elsewhere), caused_by (string[]), leads_to (string[]), and timestamp
(string, ISO 8601) to the MemorySearchResult interface/type definition; ensure
any references to MemorySearchResult (e.g., functions that deserialize search
results) accept and preserve these fields and adjust imports/types if a shared
enum/type (for signals) exists.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 827d3335-04fc-4a71-9638-4865ea29c0b0

📥 Commits

Reviewing files that changed from the base of the PR and between 00b85dc and 39ca729.

📒 Files selected for processing (2)
  • src/memory-runtime.ts
  • src/memory-tools.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/memory-runtime.ts

Comment thread src/memory-tools.ts
Comment on lines +202 to +203
"- caused_by: array of upstream causal event IDs (why this happened). Use memory_get with these IDs to walk backward through the causal chain.\n" +
"- leads_to: array of downstream procedural event IDs (what this caused). Use memory_get with these IDs to walk forward through the event DAG.\n" +

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't tell callers to pass graph IDs into memory_get.

Lines 202-203 describe caused_by/leads_to as event IDs, but memory_get only accepts a path returned by memory_search (see Lines 107-125 and Lines 265-266). This guidance sends the model down an unsupported call path.

Suggested wording
-          "- caused_by: array of upstream causal event IDs (why this happened). Use memory_get with these IDs to walk backward through the causal chain.\n" +
-          "- leads_to: array of downstream procedural event IDs (what this caused). Use memory_get with these IDs to walk forward through the event DAG.\n" +
+          "- caused_by: array of upstream causal event IDs (why this happened). Use these IDs to correlate related memories or issue a targeted memory_search to walk backward through the causal chain.\n" +
+          "- leads_to: array of downstream procedural event IDs (what this caused). Use these IDs to correlate related memories or issue a targeted memory_search to walk forward through the event DAG.\n" +
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"- caused_by: array of upstream causal event IDs (why this happened). Use memory_get with these IDs to walk backward through the causal chain.\n" +
"- leads_to: array of downstream procedural event IDs (what this caused). Use memory_get with these IDs to walk forward through the event DAG.\n" +
"- caused_by: array of upstream causal event IDs (why this happened). Use these IDs to correlate related memories or issue a targeted memory_search to walk backward through the causal chain.\n" +
"- leads_to: array of downstream procedural event IDs (what this caused). Use these IDs to correlate related memories or issue a targeted memory_search to walk forward through the event DAG.\n" +
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/memory-tools.ts` around lines 202 - 203, The doc text incorrectly
instructs callers to pass event IDs from caused_by/leads_to into memory_get;
memory_get expects a path produced by memory_search, not raw event IDs. Update
the wording around the caused_by and leads_to descriptions to either (a) tell
callers to call memory_search with those event IDs to obtain a path and then
pass that path to memory_get, or (b) say to use memory_get only with paths
returned by memory_search and to use memory_get/memory_search together to walk
the causal chain; reference symbols: caused_by, leads_to, memory_get,
memory_search.

@compoodment

Copy link
Copy Markdown
Collaborator

Vale Review

Verdict: not merge-ready. The runtime enrichment idea is sound, but this branch currently conflicts with main and the public tool contract has two sharp edges that will mislead agents.

Findings

  1. Blocker: this PR conflicts with current main and would drop newer memory_search guidance.

GitHub reports the PR as CONFLICTING. I also checked with git merge-tree upstream/main upstream/pr-301, which produces a content conflict in src/memory-tools.ts.

The conflict matters: current main has tightened the memory_search description with the anti-loop instruction:

Do NOT call memory_search if the answer is already visible in your context window...

The PR replaces that description with the new result-field docs. When rebasing, keep both pieces: the anti-loop guidance from main and the new metadata-field documentation.

  1. Major: the docs tell callers to pass graph edge IDs into memory_get, but memory_get accepts only search-result paths.

In src/memory-tools.ts:202-203, the new description says:

  • caused_by: “Use memory_get with these IDs...”
  • leads_to: “Use memory_get with these IDs...”

That is wrong for the actual tool contract. MEMORY_GET_SCHEMA requires path, and its description says “A path returned by memory_search.” Raw why_ids / how_ids are not encoded search paths and are not inserted into returnedSearchPaths by memory-runtime.ts, so memory_get will reject them with the existing hidden-path guard.

Fix direction: either expose resolvable paths alongside the graph IDs, or describe these IDs as correlation/search keys, not direct memory_get inputs.

  1. Medium: memory_signals is surfaced with a type assertion instead of runtime shape checking.

In src/memory-runtime.ts:135 and src/memory-runtime.ts:321:

const signals = meta.memory_signals as string[] | undefined;

Then the code checks signals.length. If metadata contains a string, this leaks a string into signals even though the documented result field is an array/bitmask concept. If metadata contains a different non-array shape, behavior becomes inconsistent.

Use the same defensive pattern as why_ids / how_ids, or explicitly support the real stored shape if memory_signals is not always string[].

  1. Test gap: the new output contract is not locked down.

This PR changes both legacy and structured result paths, but adds no tests. I would want focused tests for:

  • legacy manager.search("query") returning kind, signals, caused_by, leads_to, and timestamp
  • structured manager.search({ query }) returning the same fields
  • malformed metadata does not leak bad shapes into signals
  • valid numeric ts and ISO-ish string timestamps normalize as expected
  • invalid/out-of-range timestamps are silently omitted, matching the new guard

Positive notes

The actual enrichment in src/memory-runtime.ts is small and correctly keeps daemon behavior unchanged. why_ids / how_ids are defensively filtered. The out-of-range toISOString guard is also good.

CI / verification state

I found no GitHub Actions runs for head 39ca729. The only reported status is CodeRabbit success. That is not enough for a tool-contract change; rebase, fix the contract docs, add the tests above, then rerun the relevant unit/type/build gates.

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