Files
999/scripts/sync_kb_asset.py

104 lines
4.0 KiB
Python

#!/usr/bin/env python3
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
ENRICHER = ROOT / 'oracle_enricher'
KB_FILE = ENRICHER / 'out' / 'oracle_kb.json'
DOSSIERS_DIR = ENRICHER / 'out' / 'dossiers'
LEXICON_FILE = ENRICHER / 'data' / 'lexicon.json'
OUT_FILE = ROOT / 'assets' / 'data' / 'oracle_kb.json'
SEEDS = {'огонь', 'вода', 'волк', 'ключ', 'над', 'я', 'зеркало', 'путь', 'смерть', 'лишь'}
def main():
lexicon = json.loads(LEXICON_FILE.read_text(encoding='utf-8'))
kb = json.loads(KB_FILE.read_text(encoding='utf-8')) if KB_FILE.exists() else {}
# Pre-map dossiers by word
dossiers = {}
for p in DOSSIERS_DIR.glob('*.json'):
try:
d = json.loads(p.read_text(encoding='utf-8'))
w = d.get('word')
if w:
dossiers[w] = d
except Exception:
pass
out_data = {}
real_canon_count = 0
for row in lexicon:
w = row['word']
w_id = row['id']
w_emoji = row.get('emoji', '')
dossier = dossiers.get(w, {})
canon = kb.get(w) or dossier.get('canon') or {}
is_seed = w in SEEDS
is_llm_canon = canon.get('via') in ('grok_cli', 'user_edit')
is_user_edited = bool(canon.get('user_edited'))
has_canon = is_seed or is_llm_canon or is_user_edited or (bool(canon.get('core')) and bool(canon.get('oracle')))
if has_canon:
real_canon_count += 1
core = canon.get('core') or ''
oracle = canon.get('oracle') or ''
layers = canon.get('layers') or []
shadow = canon.get('shadow') or ''
asks = canon.get('asks') or ''
step = canon.get('step') or ''
binds = canon.get('binds') or []
grammar = canon.get('grammar') or {
'operator': dossier.get('operator') or 'substance',
'valence': dossier.get('valence') or 'liminal',
'modifies': ''
}
else:
core = ''
oracle = ''
layers = []
shadow = (dossier.get('shadow_aspects') and ', '.join(dossier['shadow_aspects'])) or ''
asks = ''
step = ''
binds = []
grammar = {
'operator': dossier.get('operator') or 'substance',
'valence': dossier.get('valence') or 'liminal',
'modifies': ''
}
entry = {
'id': w_id,
'word': w,
'emoji': w_emoji,
'pos': row.get('pos') or dossier.get('pos') or canon.get('pos') or '',
'category': row.get('category') or dossier.get('category') or canon.get('category') or '',
'family': dossier.get('family') or canon.get('family') or '',
'operator': dossier.get('operator') or (canon.get('grammar') or {}).get('operator') or 'substance',
'valence': dossier.get('valence') or (canon.get('grammar') or {}).get('valence') or 'liminal',
'jurisdictions': dossier.get('jurisdictions') or canon.get('jurisdictions') or ['I'],
'lookup': dossier.get('lookup') or canon.get('lookup') or 'C',
'sources': dossier.get('sources') or [],
'has_canon': has_canon,
'user_edited': is_user_edited,
'core': core,
'oracle': oracle,
'layers': layers,
'shadow': shadow,
'asks': asks,
'step': step,
'binds': binds,
'grammar': grammar,
}
# Keyed both by word name AND by string id
out_data[w] = entry
out_data[str(w_id)] = entry
OUT_FILE.parent.mkdir(parents=True, exist_ok=True)
OUT_FILE.write_text(json.dumps(out_data, ensure_ascii=False, indent=2), encoding='utf-8')
print(f'Synchronized {len(lexicon)} words (total keys: {len(out_data)}) into {OUT_FILE} (real canons: {real_canon_count})')
if __name__ == '__main__':
main()