How MemPalace Handles Fact Invalidation in Its Temporal Knowledge Graph
MemPalace handles fact invalidation by closing the temporal interval on existing triples, setting the valid_to column to a specified end date while preserving the complete historical record in its SQLite-backed knowledge graph.
MemPalace implements a temporal knowledge graph that tracks when facts become true and when they cease to be valid. Unlike deletion, fact invalidation preserves the assertion history by updating time-bound columns rather than removing rows, enabling point-in-time queries while maintaining data integrity through ACID-compliant SQLite operations.
Temporal Data Model in the Triples Table
At the core of MemPalace's invalidation strategy is the triples table schema defined in mempalace/knowledge_graph.py. Each fact is stored as a temporal triple with valid_from and valid_to columns defined as TEXT fields containing ISO-8601 formatted timestamps.
When a fact is first asserted via add_triple, it enters the graph with valid_to set to NULL, indicating an active, currently valid assertion. The valid_from timestamp defaults to the insertion time, creating an open-ended interval that remains valid until explicitly closed through invalidation.
The invalidate Method Implementation
The KnowledgeGraph.invalidate() method implements a three-step process to retire facts without deleting them. Located in mempalace/knowledge_graph.py (lines 40-60), this method ensures atomic updates through SQLite's WAL mode and per-instance locking.
Locating Active Facts
First, the method queries the triples table for rows matching the specified subject, predicate, and object where valid_to IS NULL. This SELECT operation at lines 40-44 identifies exactly the active fact instances that require invalidation, preventing accidental modification of already expired records.
Temporal Validation
Before applying the invalidation, the method validates the supplied ended parameter (defaulting to the current date) using sanitize_iso_temporal from mempalace/config.py. The validation logic at lines 46-55 raises a ValueError if the end date precedes the fact's valid_from timestamp, protecting against inverted intervals where a fact would appear to end before it began.
Marking Facts as Expired
Finally, the UPDATE statement at lines 57-60 sets valid_to to the normalized ISO timestamp. This operation closes the temporal interval while preserving the original assertion record. After this update, the fact remains in the database but is tagged as expired for all subsequent queries that filter on temporal boundaries.
Thread Safety and Atomicity
MemPalace ensures safe concurrent invalidation through SQLite's Write-Ahead Logging (WAL) mode combined with explicit mutex locking. All write operations, including invalidate, acquire self._lock before executing SQL transactions.
This design prevents race conditions when multiple processes attempt to modify the same fact simultaneously. The WAL mode provides immediate persistence while allowing concurrent reads during write operations, ensuring that query methods never observe partially invalidated states.
Query Behavior with Invalidated Facts
Once invalidated, facts are automatically excluded from temporal queries through the _temporal_filter_sql helper method. Both query_entity and query_relationship apply this filter when an as_of parameter is specified, comparing the query timestamp against the valid_from and valid_to boundaries.
Facts with valid_to set to a historical timestamp will only appear in queries where the as_of date falls within the valid interval. Current queries omit expired facts entirely, effectively treating them as logically deleted while retaining the audit trail for historical reconstruction.
Practical Implementation Example
The following example demonstrates invalidating a fact when a condition no longer applies:
from mempalace.knowledge_graph import KnowledgeGraph
# Initialize the knowledge graph
kg = KnowledgeGraph()
# Assert that Max has a sports injury starting January 1st, 2025
kg.add_triple(
subject="Max",
predicate="has_issue",
obj="sports_injury",
valid_from="2025-01-01"
)
# Verify the active fact exists
active_facts = kg.query_entity("Max")
# Returns the triple with valid_to: None
# Invalidate when the injury resolves on February 15th, 2026
kg.invalidate(
subject="Max",
predicate="has_issue",
obj="sports_injury",
ended="2026-02-15"
)
# The fact now shows valid_to: "2026-02-15T00:00:00Z"
# and will be excluded from current queries
This pattern maintains complete provenance: the database retains the full history of Max's injury from onset to resolution, while application logic treats the expired assertion as inactive for current-state queries.
Summary
- MemPalace uses temporal triples with
valid_fromandvalid_tocolumns in SQLite to track fact lifespans without deletion. - The
invalidatemethod inmempalace/knowledge_graph.pyperforms an UPDATE operation on rows wherevalid_to IS NULL, preserving the original assertion data. - Input validation in the
sanitize_iso_temporalutility prevents inverted intervals where an end date precedes the start date. - Thread-safe locking (
self._lock) and SQLite WAL mode ensure atomic, race-condition-free invalidation operations. - Temporal query filters automatically exclude invalidated facts from
query_entityandquery_relationshipresults when querying current states, while still allowing retrieval via historicalas_ofparameters.
Frequently Asked Questions
Does invalidation delete facts from the MemPalace knowledge graph?
No. Invalidation performs an UPDATE operation on the triples table, setting the valid_to timestamp while preserving the original row. This soft-delete approach maintains complete audit trails and enables historical point-in-time analysis without data loss.
What happens if I attempt to invalidate a fact with an end date earlier than its start date?
The invalidate method raises a ValueError during the validation phase at lines 46-55 of knowledge_graph.py. This check ensures temporal consistency by preventing the creation of invalid intervals where valid_to would be earlier than valid_from.
How does MemPalace ensure thread safety during fact invalidation?
The implementation uses a per-instance lock (self._lock) acquired before all write operations, combined with SQLite's WAL (Write-Ahead Logging) mode. This prevents race conditions when multiple threads attempt to invalidate facts simultaneously while allowing concurrent read access to the knowledge graph.
Are invalidated facts visible in entity queries?
Invalidated facts are automatically filtered out of current-state queries through the _temporal_filter_sql mechanism. However, they remain visible when querying with an explicit as_of timestamp that falls within the fact's valid interval, enabling temporal reconstruction of past knowledge states.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →