#!/usr/bin/env python3 """ scripts/import_user_edits.py Imports custom edits made on a mobile device (exported from Oracle 999 app) into the desktop repository: - Updates the respective dossiers in oracle_enricher/out/dossiers/ - Updates oracle_enricher/out/oracle_kb.json - Automatically regenerates assets/data/oracle_kb.json via sync_kb_asset.py - Preserves git traceability with timestamps and user_edited flags Usage: # From a file: python3 scripts/import_user_edits.py edits.json # Interactive paste: python3 scripts/import_user_edits.py """ import sys import json import subprocess from pathlib import Path from datetime import datetime, timezone ROOT = Path(__file__).resolve().parent.parent ENRICHER = ROOT / 'oracle_enricher' DOSSIERS_DIR = ENRICHER / 'out' / 'dossiers' KB_FILE = ENRICHER / 'out' / 'oracle_kb.json' SYNC_SCRIPT = ROOT / 'scripts' / 'sync_kb_asset.py' def load_input_json(): if len(sys.argv) > 1 and sys.argv[1] not in ('-', '--stdin'): p = Path(sys.argv[1]) if not p.exists(): print(f"Error: File not found: {p}") sys.exit(1) return json.loads(p.read_text(encoding='utf-8')) if not sys.stdin.isatty(): return json.loads(sys.stdin.read()) print("=== Импорт пользовательских правок из Оракула 999 ===") print("Вставьте JSON с телефона (скопированный через кнопку 'Скопировать JSON правок')") print("После вставки введите строку с 'EOF' или нажмите Ctrl+D:") lines = [] try: while True: line = input() if line.strip() == 'EOF': break lines.append(line) except EOFError: pass raw = '\n'.join(lines).strip() if not raw: print("Отмена: входные данные пусты.") sys.exit(0) return json.loads(raw) def main(): data = load_input_json() if not isinstance(data, dict): print("Ошибка: ожидался словарь вида { 'слово': { ... } }") sys.exit(1) print(f"Найдено правок для импорта: {len(data)} слов") # Index existing dossiers word_to_dossier = {} if DOSSIERS_DIR.exists(): for p in DOSSIERS_DIR.glob('*.json'): try: d = json.loads(p.read_text(encoding='utf-8')) w = d.get('word') if w: word_to_dossier[w.lower().strip()] = p except Exception: pass kb = json.loads(KB_FILE.read_text(encoding='utf-8')) if KB_FILE.exists() else {} now_iso = datetime.now(timezone.utc).isoformat() updated_words = [] for raw_word, edits in data.items(): w = raw_word.lower().strip() if not isinstance(edits, dict): continue core = edits.get('core', '').strip() oracle = edits.get('oracle', '').strip() shadow = edits.get('shadow', '').strip() asks = edits.get('asks', '').strip() step = edits.get('step', '').strip() # 1. Update dossier if exists p = word_to_dossier.get(w) if p and p.exists(): try: dossier = json.loads(p.read_text(encoding='utf-8')) except Exception: dossier = {'word': w} else: p = DOSSIERS_DIR / f"{w}.json" dossier = {'word': w} if 'canon' not in dossier or not isinstance(dossier['canon'], dict): dossier['canon'] = {'word': w} canon = dossier['canon'] if core: canon['core'] = core if oracle: canon['oracle'] = oracle if shadow: canon['shadow'] = shadow if asks: canon['asks'] = asks if step: canon['step'] = step canon['user_edited'] = True canon['via'] = 'user_edit' canon['updated_at'] = edits.get('updatedAt') or now_iso p.parent.mkdir(parents=True, exist_ok=True) p.write_text(json.dumps(dossier, ensure_ascii=False, indent=2), encoding='utf-8') # 2. Update oracle_kb.json if w not in kb or not isinstance(kb[w], dict): kb[w] = canon else: kb[w].update({ 'core': canon.get('core', ''), 'oracle': canon.get('oracle', ''), 'shadow': canon.get('shadow', ''), 'asks': canon.get('asks', ''), 'step': canon.get('step', ''), 'user_edited': True, 'via': 'user_edit', 'updated_at': canon.get('updated_at'), }) updated_words.append(w) KB_FILE.parent.mkdir(parents=True, exist_ok=True) KB_FILE.write_text(json.dumps(kb, ensure_ascii=False, indent=2), encoding='utf-8') print(f"Обновлено досье и KB для {len(updated_words)} слов: {', '.join(updated_words[:10])}{'...' if len(updated_words) > 10 else ''}") # 3. Synchronize assets/data/oracle_kb.json print("Синхронизация assets/data/oracle_kb.json...") subprocess.run([sys.executable, str(SYNC_SCRIPT)], check=True) print("\n✅ УСПЕШНО! Все правки зафиксированы в кодовой базе.") print("Теперь они станут частью базового канона во всех будущих релизах приложения.") print("Чтобы закоммитить в git:") print(" git add oracle_enricher/ assets/data/oracle_kb.json") print(" git commit -m 'feat: import user canon edits from mobile app'") if __name__ == '__main__': main()