diff --git a/extract-decisions.py b/extract-decisions.py index 46c5421..97068f1 100644 --- a/extract-decisions.py +++ b/extract-decisions.py @@ -28,9 +28,10 @@ import yaml OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions" MODEL = "anthropic/claude-sonnet-4.5" USAGE_CSV = "/opt/teleo-eval/logs/openrouter-usage.csv" -REPO_DIR = Path("/opt/teleo-eval/workspaces/main") -ARCHIVE_DIR = REPO_DIR / "inbox" / "archive" -DECISIONS_DIR = REPO_DIR / "decisions" +MAIN_REPO = Path("/opt/teleo-eval/workspaces/main") +REPO_DIR = Path("/opt/teleo-eval/workspaces/extract") +ARCHIVE_DIR = MAIN_REPO / "inbox" / "archive" # Read sources from main (canonical) +DECISIONS_DIR = REPO_DIR / "decisions" # Write records to extract worktree # ─── LLM Call ─────────────────────────────────────────────────────────────── @@ -123,17 +124,16 @@ def find_proposal_sources() -> list[Path]: # ─── Check if Decision Record Exists ──────────────────────────────────────── def decision_exists(slug: str, domain: str = "internet-finance") -> bool: - """Check if a decision record already exists.""" - target_dir = DECISIONS_DIR / domain - if not target_dir.exists(): - return False - # Check exact slug match - if (target_dir / f"{slug}.md").exists(): - return True - # Check partial match (slug might be truncated) - for f in target_dir.iterdir(): - if slug[:40] in f.name: + """Check if a decision record already exists in main OR extract worktree.""" + for repo in [MAIN_REPO, REPO_DIR]: + target_dir = repo / "decisions" / domain + if not target_dir.exists(): + continue + if (target_dir / f"{slug}.md").exists(): return True + for f in target_dir.iterdir(): + if slug[:40] in f.name: + return True return False @@ -344,6 +344,12 @@ def main(): print(f" {title}") return + # Prepare extract worktree: sync to main, create branch + branch_name = f"epimetheus/decisions-{date.today().isoformat()}" + if not _prepare_branch(branch_name): + print("ERROR: Failed to prepare extract worktree branch") + sys.exit(1) + processed = 0 created = 0 skipped = 0 @@ -369,6 +375,76 @@ def main(): print(f"\nDone: {processed} processed, {created} created, {skipped} skipped, {errors} errors") + # Commit and push for PR review + if created > 0: + _commit_and_push(branch_name, created) + + +def _prepare_branch(branch_name: str) -> bool: + """Sync extract worktree to main and create a new branch.""" + import subprocess + cwd = str(REPO_DIR) + try: + subprocess.run(["git", "fetch", "origin", "main"], cwd=cwd, check=True, capture_output=True) + subprocess.run(["git", "checkout", "main"], cwd=cwd, check=True, capture_output=True) + subprocess.run(["git", "reset", "--hard", "origin/main"], cwd=cwd, check=True, capture_output=True) + subprocess.run(["git", "checkout", "-b", branch_name], cwd=cwd, check=True, capture_output=True) + print(f"Branch created: {branch_name}") + return True + except subprocess.CalledProcessError as e: + print(f"ERROR preparing branch: {e.stderr.decode()[:200] if e.stderr else e}") + return False + + +def _commit_and_push(branch_name: str, count: int): + """Commit decision records and push branch for PR.""" + import subprocess + cwd = str(REPO_DIR) + token_file = Path("/opt/teleo-eval/secrets/forgejo-leo-token") + token = token_file.read_text().strip() if token_file.exists() else "" + + try: + subprocess.run(["git", "add", "decisions/"], cwd=cwd, check=True, capture_output=True) + result = subprocess.run(["git", "status", "--porcelain"], cwd=cwd, capture_output=True, text=True) + if not result.stdout.strip(): + print("No changes to commit") + return + + msg = (f"epimetheus: {count} decision records from proposal extraction\n\n" + f"Batch extraction of event_type: proposal sources into structured\n" + f"decision records with full verbatim text + LLM analysis.\n\n" + f"Pentagon-Agent: Epimetheus <3D35839A-7722-4740-B93D-51157F7D5E70>") + subprocess.run(["git", "commit", "-m", msg], cwd=cwd, check=True, capture_output=True) + subprocess.run(["git", "push", "-u", "origin", branch_name], cwd=cwd, check=True, capture_output=True) + print(f"Pushed branch: {branch_name}") + + # Create PR via Forgejo API + if token: + resp = requests.post( + "http://localhost:3000/api/v1/repos/teleo/teleo-codex/pulls", + headers={"Authorization": f"token {token}"}, + json={ + "title": f"epimetheus: {count} decision records from proposal extraction", + "body": (f"## Summary\n" + f"- {count} decision records extracted from archived proposal sources\n" + f"- Full verbatim proposal text + LLM-generated summary/significance\n" + f"- Both decision markets and fundraises\n\n" + f"## Source\n" + f"Extracted by `extract-decisions.py` from `event_type: proposal` sources in archive/"), + "head": branch_name, + "base": "main", + }, + timeout=30, + ) + if resp.status_code in (200, 201): + pr_url = resp.json().get("html_url", "") + print(f"PR created: {pr_url}") + else: + print(f"WARNING: PR creation failed ({resp.status_code}): {resp.text[:200]}") + + except subprocess.CalledProcessError as e: + print(f"ERROR committing: {e.stderr.decode()[:200] if e.stderr else e}") + if __name__ == "__main__": main()