#!/usr/bin/env python3 """Shared utilities for Settled Reach DB tooling scripts. Provides the standard DB path resolution, config loading, and connection helpers used across ticket, sprint, sqlite_connector, and decisions_sync. """ import json import os import sqlite3 import sys from pathlib import Path # --------------------------------------------------------------------------- # Paths # --------------------------------------------------------------------------- SCRIPT_DIR = Path(__file__).resolve().parent CONFIG_PATH = SCRIPT_DIR / "config.json" WORKTREE_ROOT = (SCRIPT_DIR / ".." / "..").resolve() # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def resolve_db_path() -> Path: """Return the ticket database path. Prefers the SR_DB_PATH environment variable (absolute path). Falls back to /settledreach.db — the shared DB location used when working directly in the main repo checkout. """ if os.environ.get("SR_DB_PATH"): return Path(os.environ["SR_DB_PATH"]).resolve() return (WORKTREE_ROOT / ".." / "settledreach.db").resolve() def load_config() -> dict: """Load tooling/db/config.json and inject the resolved DB path.""" with open(CONFIG_PATH) as f: cfg = json.load(f) cfg["sqlite_db_resolved"] = str(resolve_db_path()) return cfg def get_connection(cfg: dict) -> sqlite3.Connection: """Return a WAL-mode SQLite connection with foreign keys enabled.""" conn = sqlite3.connect(cfg["sqlite_db_resolved"]) conn.execute("PRAGMA journal_mode=WAL;") conn.execute("PRAGMA foreign_keys=ON;") conn.row_factory = sqlite3.Row return conn def ensure_venv() -> None: """Re-exec into the project .venv Python if not already running there. Call this at the top of any script that uses third-party packages, before those imports. Pure-stdlib scripts (ticket, sprint, sqlite_connector, decisions_sync) do not need it. Usage:: from common import ensure_venv ensure_venv() import numpy as np # third-party import follows """ venv_python = WORKTREE_ROOT / ".venv" / "bin" / "python" # Already running inside the venv — nothing to do. if Path(sys.executable).resolve() == venv_python.resolve(): return # .venv not set up yet — fail with a helpful message. if not venv_python.exists(): print( "error: .venv not found — run `make setup-venv` first.", file=sys.stderr, ) sys.exit(1) # Re-exec into the venv Python, preserving all arguments. os.execv(str(venv_python), [str(venv_python)] + sys.argv)