feat(episodic): persist whitelisted episode_metadata provenance keys as node properties (FalkorDB/Neo4j)#2
Conversation
…as node properties (FalkorDB/Neo4j)
Watercooler A1-full (thread audit-transport-modes-hosted-db-2026-07,
completion sequence Wave 4): entry_id/thread_id/chunk_index/total_chunks
from episode_metadata become first-class Episodic properties so they
survive the providers' full-map 'SET n = {...}' writes (a post-hoc
stamp is wiped on the next re-save) and are indexable
(:Episodic(entry_id) for provenance backtraces).
- add_episode / RawEpisode gain episode_metadata passthrough into
EpisodicNode (the field existed on the model but was never plumbed).
- EpisodicNode.save flattens EPISODIC_PROVENANCE_KEYS into the save
params, gated to FalkorDB/Neo4j (Kuzu has a typed schema — unknown
params error; Neptune untested — both skipped with in-code notes).
- Single + bulk save queries for FalkorDB/Neo4j write the four fields;
Kuzu/Neptune queries unchanged.
- bulk path: add_nodes_and_edges_bulk_tx flattens per episode dict,
same provider gate.
Tests: driver-free unit tests (params carry/omit per provider; query
text references; Kuzu/Neptune untouched) — dependency-free via
asyncio.run so they pass with or without pytest-asyncio. Live-validated
against a real FalkorDB: properties persist, survive full-map re-save,
and default to null without metadata.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: calebjacksonhoward <calebjhoward@gmail.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Evidence basis for merge (the inherited
Follow-up chore filed separately: point the inherited workflows at |
calebjacksonhoward
left a comment
There was a problem hiding this comment.
Found one blocking issue.
graphiti_core/models/nodes/node_db_queries.py now makes the FalkorDB/Neo4j single-save query require $entry_id, $thread_id, $chunk_index, and $total_chunks, but the provider operations paths were not updated. graphiti_core/driver/falkordb/operations/episode_node_ops.py and graphiti_core/driver/neo4j/operations/episode_node_ops.py still build the old params dict in save(), then call the same changed query, so graphiti.nodes.episode.save(...) will execute with missing parameters. Their save_bulk() paths also serialize dict(node) without flattening the whitelisted episode_metadata keys, so the new bulk query will not persist the intended provenance through the operations/namespace API.
Why this changes the decision likelihood: this PR’s stated purpose is to make the whitelisted provenance survive episode saves for FalkorDB/Neo4j. If the operations/namespace save paths either fail at runtime or omit those fields, the feature is only partially implemented and callers using the new operations API can still lose or fail to write the provenance the PR is meant to preserve.
Please update the FalkorDB and Neo4j EpisodeNodeOperations.save() and save_bulk() implementations to use the same provenance flattening/defaulting as EpisodicNode.save() and add_nodes_and_edges_bulk_tx(), and add coverage for at least one operations-path save so this does not regress.
I also tried to run python -m pytest tests/test_episodic_provenance.py -q, but this local clone is missing the neo4j dependency, so pytest stopped during conftest import before running the test file.
…deNodeOperations save paths (PR #2 review) The review caught that the FalkorDB/Neo4j operations-interface save() built its own params dict against the changed full-map query — missing the now-required provenance params (runtime failure) — and save_bulk() serialized dict(node) without flattening episode_metadata (silent provenance drop). Both now apply the same EPISODIC_PROVENANCE_KEYS flattening/defaulting as EpisodicNode.save() and add_nodes_and_edges_bulk_tx(). Five operations-path tests added (save carry/default, bulk flatten, both providers); note the plain FalkorDB driver does not activate the operations interface, so the classic path remains the one our deployment exercises — this closes the gap for callers that do enable it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: calebjacksonhoward <calebjhoward@gmail.com>
|
Blocking finding addressed in Both Scope note verified live: the plain |
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
calebjacksonhoward
left a comment
There was a problem hiding this comment.
Rereviewed the fix at eb3bfc4080b42a3c2ea261821c60cee986f25953.
The prior blocking concern is addressed. The FalkorDB and Neo4j EpisodeNodeOperations.save() paths now add the whitelisted provenance params with None defaults, and their save_bulk() paths flatten the same keys into each episode dict before calling the updated bulk queries. The added tests cover the operations-path regression for single and bulk saves.
I do not have further code findings from this pass.
Verification note: I retried python -m pytest tests/test_episodic_provenance.py -q, but this local clone still fails during conftest import because the environment is missing neo4j (ModuleNotFoundError: No module named 'neo4j'). GitHub currently still reports CLAAssistant/triage failing and pyright/unit-tests/database-integration-tests/ruff pending, so those checks still need to settle independently.
Summary
Watercooler A1-full (completion-sequence Wave 4, Codex-approved plan
01KX0AMDMN0R0VX335PQYDW4M3inaudit-transport-modes-hosted-db-2026-07): the four provenance keys (entry_id,thread_id,chunk_index,total_chunks) fromepisode_metadatabecome first-classEpisodicproperties, because the FalkorDB/Neo4j save queries write a full property map (SET n = {…}) — a post-hoc stamp is wiped on the next re-save. First-class properties are also indexable (:Episodic(entry_id)for provenance backtraces).Changes
add_episodeandRawEpisodegainepisode_metadatapassthrough intoEpisodicNode— the field existed on the model but was never plumbed and never persisted on FalkorDB.EpisodicNode.saveflattensEPISODIC_PROVENANCE_KEYSinto save params, provider-gated to FalkorDB/Neo4j: Kuzu has a typed schema (unknown params error), Neptune untested — both skipped with in-code notes.add_nodes_and_edges_bulk_tx) flattens per episode dict under the same gate.Validation
tests/test_episodic_provenance.py): params carry/omit per provider, query-text references, Kuzu/Neptune untouched. Dependency-free (asyncio.run).🤖 Generated with Claude Code