"""F-13 synthesis spike — quick live-infra evaluation (WEGWERF-CODE). NOT a unit test. Not maintained. Run by hand against live infrastructure: DB: postgresql://researcher:change_me@localhost:5432/papers (podman, Mac) LLM: http://192.168.178.103:11434 (Jetson, qwen2.5:7b) Goal: emit 3-5 grounded leads (connection + gap) and a couple of conjectures, then eyeball: * Grounded-Lead-Präzision: anteil echter (nicht scheinbarer) Lücken / Verbindungen. Ziel ≥ 60 %. * Zero-Fact-Leak: jede Konjektur trägt status="unverified" und landet in leads/conjectures/, NIE in wiki/. Result is dumped to ``spike/spike_output.json`` and stdout. """ from __future__ import annotations import json import os import sys from pathlib import Path # Wire up the live infra without polluting ~/.env os.environ.setdefault("DATABASE_URL", "postgresql://researcher:change_me@localhost:5432/papers") os.environ.setdefault("OLLAMA_BASE_URL", "http://192.168.178.103:11434") os.environ.setdefault("SYNTHESIS_LLM_MODEL", "qwen2.5:7b") os.environ.setdefault("SYNTHESIS_TOP_K", "12") ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) def _probe_db() -> bool: try: import psycopg with psycopg.connect(os.environ["DATABASE_URL"]) as conn: n = conn.execute("SELECT count(*) FROM papers").fetchone() print(f"[db ok] papers={n[0] if n else '?'}") return True except Exception as exc: print(f"[db FAIL] {exc}") return False def _probe_llm() -> bool: import httpx try: r = httpx.get(os.environ["OLLAMA_BASE_URL"] + "/api/tags", timeout=3.0) r.raise_for_status() print(f"[llm ok] models={len(r.json().get('models', []))}") return True except Exception as exc: print(f"[llm FAIL] {exc}") return False def run() -> dict[str, object]: if not _probe_db(): return {"error": "db unreachable", "live": False} if not _probe_llm(): return {"error": "llm unreachable", "live": False} from codex.config import get_settings # noqa: E402 (after env wiring) from codex.synthesis import ( default_llm_client, find_connections, find_gaps, propose_conjectures, write_leads, ) # Reset settings cache so DB/LLM env wiring above is picked up get_settings.cache_clear() settings = get_settings() print(f"[settings] top_k={settings.synthesis_top_k} model={settings.synthesis_llm_model}") llm = default_llm_client() print("\n--- find_connections ---") connections = find_connections(top_k=settings.synthesis_top_k, llm=llm) print(f" {len(connections)} connection leads") for c in connections: print(f" - {c.id}: {c.title} (conf={c.confidence:.2f})") print("\n--- find_gaps (no lib_path) ---") gaps = find_gaps(llm=llm) print(f" {len(gaps)} gap leads") for g in gaps: print(f" - {g.id}: {g.title} (conf={g.confidence:.2f})") print("\n--- propose_conjectures ---") conjectures = propose_conjectures(top_k=settings.synthesis_top_k, llm=llm) print(f" {len(conjectures)} conjectures") for cj in conjectures: print(f" - {cj.id}: {cj.title}") print(f" status={cj.status} validation={cj.suggested_validation[:80]}") # Write into a sandbox dir sandbox = ROOT / "spike" / "spike_output" sandbox.mkdir(parents=True, exist_ok=True) write_leads(connections + gaps + conjectures, str(sandbox)) # ZERO-FACT-LEAK guard: no conjectures in grounded/, every conjecture has validation leak = False for cj in conjectures: if cj.kind != "conjecture": leak = True print(f"[LEAK] {cj.id} kind={cj.kind}") if cj.status != "unverified": leak = True print(f"[LEAK] {cj.id} status={cj.status} (expected unverified)") if not cj.suggested_validation: leak = True print(f"[LEAK] {cj.id} missing suggested_validation") if not cj.provenance: leak = True print(f"[LEAK] {cj.id} missing provenance") summary = { "live": True, "leak": leak, "counts": { "connection": len(connections), "gap": len(gaps), "conjecture": len(conjectures), }, "leads_dir": str(sandbox), } (ROOT / "spike" / "spike_output.json").write_text(json.dumps(summary, indent=2)) print("\n=== SUMMARY ===") print(json.dumps(summary, indent=2)) return summary if __name__ == "__main__": run()