"""Bounded synthetic checks of actual MemPalace develop source; no LLM/embeddings/mocks."""
import json, sys
from pathlib import Path
sys.path.insert(0, '/src')
from mempalace.knowledge_graph import KnowledgeGraph
from mempalace.lexical import tokenize, bm25_scores
R=Path('/work'); checks=[]
def check(name,condition):
 checks.append({'name':name,'passed':bool(condition)})
 if not condition:raise AssertionError(name)
g=KnowledgeGraph(str(R/'synthetic.sqlite'))
check('fresh_graph_is_empty',g.stats()['triples']==0 and g.stats()['entities']==0)
check('unknown_entity_returns_no_claims',g.query_entity('nonexistent')==[])
first=g.add_triple('Fixture Project','uses','SQLite',valid_from='2026-01-01',source_drawer_id='fixture-source-1',adapter_name='manual-fixture')
check('writes_real_sqlite_triple',bool(first) and g.stats()['triples']==1)
row=g.query_entity('Fixture Project',as_of='2026-02-01')[0]
check('readback_preserves_object',row['object']=='SQLite')
check('source_drawer_provenance_stored',g.dump_rows('triples')[0]['source_drawer_id']=='fixture-source-1')
check('no_fact_before_start',g.query_entity('Fixture Project',as_of='2025-12-31')==[])
duplicate=g.add_triple('Fixture Project','uses','SQLite',valid_from='2026-01-01')
check('identical_current_fact_deduplicated',duplicate==first and g.stats()['triples']==1)
nextid=g.supersede('Fixture Project','uses','SQLite','PostgreSQL',at='2026-03-01T12:00:00Z',source_drawer_id='fixture-source-2')
check('supersede_keeps_history',nextid!=first and g.stats()['triples']==2 and g.stats()['expired_facts']==1)
check('historical_query_returns_previous_value',[x['object'] for x in g.query_entity('Fixture Project',as_of='2026-03-01T11:59:59Z')]==['SQLite'])
check('boundary_returns_only_successor',[x['object'] for x in g.query_entity('Fixture Project',as_of='2026-03-01T12:00:00Z')]==['PostgreSQL'])
try:g.add_triple('Bad','uses','Thing',valid_from='2026-05-01',valid_to='2026-04-01')
except ValueError:rejected=True
else:rejected=False
check('inverted_interval_rejected',rejected and g.stats()['triples']==2)
g.add_triple('مشروع تجريبي','uses','قاعدة محلية',valid_from='2026-01-01')
check('arabic_entity_roundtrip',g.query_entity('مشروع تجريبي',as_of='2026-02-01')[0]['object']=='قاعدة محلية')
g.add_triple("O'Brien; DROP TABLE triples;--",'uses','Fixture',valid_from='2026-01-01')
check('quoted_entity_is_data_not_sql',g.stats()['triples']==4 and len(g.query_entity("O'Brien; DROP TABLE triples;--"))==1)
g.close();g=KnowledgeGraph(str(R/'synthetic.sqlite'))
check('sqlite_persists_across_reopen',[x['object'] for x in g.query_entity('Fixture Project',as_of='2026-04-01')]==['PostgreSQL'])
check('unicode_lexical_tokenization',tokenize('قرار مشروع قاعدة')==['قرار','مشروع','قاعدة'])
scores=bm25_scores('database policy',['database policy requires PostgreSQL','banana orchard fruit',''])
check('lexical_positive_and_negative_control',scores[0]>0 and scores[1]==0 and scores[2]==0)
g.close()
out={'source_revision':'84582fb055a6429261f9c779da86c0561ec80adc','source_track':'develop; pyproject declares 3.12.0, not released v3.11.0','scope':'Actual SQLite temporal graph and lexical helpers only. Synthetic manually supplied facts; no model, vector retrieval, automatic extraction, MCP, hook integration, agent-brain execution, or comparative benchmark.','mocks':False,'network':False,'passed':sum(x['passed'] for x in checks),'failed':sum(not x['passed'] for x in checks),'checks':checks}
assert out['failed']==0
print(json.dumps(out,ensure_ascii=False,indent=2))
