Skip to content

fix(consolidation): preserve temporal fields across dedup merges - #3482

Open
Sanderhoff-alt wants to merge 1 commit into
vectorize-io:mainfrom
Sanderhoff-alt:fix/3477-consolidation-temporal
Open

fix(consolidation): preserve temporal fields across dedup merges#3482
Sanderhoff-alt wants to merge 1 commit into
vectorize-io:mainfrom
Sanderhoff-alt:fix/3477-consolidation-temporal

Conversation

@Sanderhoff-alt

@Sanderhoff-alt Sanderhoff-alt commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Issue #3477 reports that dated source facts can produce observations with null occurred_start and occurred_end. The normal CREATE path already aggregates source dates, but dedup folds bypassed that writer and updated observations did not pass event_date through the PostgreSQL SQL path. As a result, merging observations could silently discard part of their temporal information.

This change makes all observation merge paths use the same null-safe rules: event_date and occurred_start keep the earliest non-null value, while occurred_end and mentioned_at keep the latest non-null value. CREATE dedup carries source-derived fields into the survivor, UPDATE dedup merges both rows before deleting the rewritten row, and external memory stores follow the same rules.

As a related fix, the ordinary observation UPDATE path now propagates event_date from the source aggregation instead of leaving it unchanged. Its PostgreSQL SQL update and external-store upsert now apply the same temporal merge rules, so updates cannot lose an earlier event date while extending an observation.

Verification

The deterministic regression tests cover CREATE and UPDATE dedup SQL, the ordinary UPDATE parameter contract, external-store folds, and min/max/null behavior. 45 dedup tests, 15 UPDATE/integrity tests, and 7 source aggregation tests pass. The existing real-LLM temporal consolidation integration test was also run with the configured test runtime; this PR does not add a new LLM integration test.

Fixes #3477

CREATE dedup folds source ids and merged text directly into the existing
observation, bypassing the normal CREATE writer. Carry all four
source-derived temporal fields into that fold and merge them null-safely.

UPDATE dedup folds the rewritten observation into the survivor before
deleting the redundant row. Merge temporal fields from both rows so the
survivor keeps the complete source interval.

The ordinary UPDATE path now passes event_date and applies the same rules:
event_date and occurred_start use the earliest non-null value; occurred_end
and mentioned_at use the latest non-null value. Apply the same merge in
external memory stores. Document why event_date uses the store snapshot in
that branch: MemoryFact does not carry event_date.

Add regression coverage for PostgreSQL CREATE/UPDATE fold SQL, ordinary
UPDATE parameters, external-store folds, and null/min/max semantics. The
external-store ordinary UPDATE test covers the newly added event_date
merge branch.

Validation:
- 45 consolidation dedup tests
- 15 UPDATE/integrity tests
- 7 source aggregation tests
- Existing real-LLM temporal consolidation integration test
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.

bug(consolidation): dated source facts can produce observations with null occurred dates

1 participant