Skip to content

fix(schema): emit unique_identifiers for @upsert/@lookup nodes#48

Open
shawkatkabbara wants to merge 2 commits into
mainfrom
fix/schema-builder-unique-identifiers
Open

fix(schema): emit unique_identifiers for @upsert/@lookup nodes#48
shawkatkabbara wants to merge 2 commits into
mainfrom
fix/schema-builder-unique-identifiers

Conversation

@shawkatkabbara

Copy link
Copy Markdown
Contributor

Problem

build_schema_params() was producing node_types without the unique_identifiers field, even though SchemaCreateParams documents it as:

Equivalent to @upsert/@lookup decorators... Properties marked as unique_identifiers are used for entity deduplication and merging.

Without this field, the memory server's _get_unique_identifiers_for_node_type() returns [] and falls back to _create_node_with_content_check, creating duplicate nodes for the same logical entity.

Reproduction

Register a schema with @upsert + prop(required=True, search=exact()):

@node
@upsert
class call:
    call_id: str = prop(required=True, search=exact())
    name: str = prop(required=False, search=semantic())

Before this PR:

{
  "name": "call",
  "properties": {...},
  "unique_identifiers": []   // ❌ empty
}

After this PR:

{
  "name": "call",
  "properties": {...},
  "unique_identifiers": ["call_id"]   // ✅ populated
}

Real-world impact

In production data we observed 11 duplicate :call nodes sharing identical call_id values, caused entirely by this gap. After running with the fix, only one node is created per call_id (server-side MERGE on unique_identifiers succeeds).

Fix

Derive unique_identifiers from properties marked required=True + search=exact() (matching the documented contract) and emit on @upsert and @lookup nodes.

Tests

Locally verified:

  • @upsert call with call_id: str = prop(required=True, search=exact())unique_identifiers: ["call_id"]
  • @lookup tactic with id: str = prop(required=True, search=exact())unique_identifiers: ["id"]
  • Nodes with no exact-search required properties → field omitted (no behavior change) ✓
  • @create (default) policy → field omitted (only emitted on upsert/lookup) ✓

deeptrust cookbook
build_schema_params() was producing node_types without the unique_identifiers
field, even though SchemaCreateParams documents it as the merge key for
@upsert/@lookup nodes (equivalent to required + search=exact() properties).

Without unique_identifiers, the memory server's _get_unique_identifiers_for_node_type()
returns [] and falls back to _create_node_with_content_check, creating
duplicate nodes for the same logical entity (e.g. multiple :call nodes
sharing the same call_id).

This patch derives unique_identifiers from properties marked
required=True + search=exact() and emits them on @upsert and @lookup nodes.

Repro: register a schema with @upsert + prop(required=True, search=exact())
and inspect the resulting node_type — the field was empty before, populated now.

Tested locally: schema build now produces unique_identifiers=['call_id']
for an @upsert call type and ['id'] for a @lookup tactic type.
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