H1 godot-cold-parse exit-code guard (+bonus: import-pass for cold checkouts, found live); H2 pr-watchlist-diff loud registry failure; H3/T1 deny list :* normalization (add-only) + uniform allow syntax; H4/T7 helper-script allows; H5 get_api_key env-only (config.json is tracked — no secret fallback); H6 TEAM.md active/standby split; H7 troblum solo-profiling note; H8 pr-review frontmatter Task->Agent; H9 conventions doc taxonomies fixed vs real tree; T2 ask-gate leash files (settings/hooks) in tracked settings; T3 R-013 cross-reference; T4 governance README index regenerated (pql decisions sync); T5 dudley briefing ACTIVE; T6 pr-process step 7 run-from-main. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
100 lines
3.4 KiB
Python
100 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Shared utilities for Settled Reach asset/connector scripts.
|
|
|
|
Provides `ensure_venv`, used by the asset connectors (audio_connector,
|
|
audio_batch, image_connector, trellis_connector) to re-exec into the project
|
|
.venv before their third-party imports, plus the connector config helpers
|
|
(`load_config`, `get_base_url`, `get_api_key`) that were formerly copy-pasted
|
|
across the connectors (T-1067 rider, S-25). The former settledreach.db
|
|
connection helpers were removed when the ticket/decision tooling was retired
|
|
(pql migration Phase 6); planning now lives in pql (`.pql/`).
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Paths
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
WORKTREE_ROOT = (SCRIPT_DIR / ".." / "..").resolve()
|
|
CONFIG_PATH = SCRIPT_DIR / "config.json"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
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.
|
|
|
|
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)
|
|
|
|
|
|
def load_config() -> dict:
|
|
"""Load the shared endpoint configuration from tooling/db/config.json."""
|
|
with open(CONFIG_PATH) as f:
|
|
return json.load(f)
|
|
|
|
|
|
def get_base_url(key: str, default: str) -> str:
|
|
"""Resolve a service base URL from config.json, with a fallback default.
|
|
|
|
Usage::
|
|
|
|
base = get_base_url("trellis_url", "http://tower-of-joy:11510")
|
|
"""
|
|
return load_config().get(key, default)
|
|
|
|
|
|
def get_api_key(env_var: str, config_key: str = "") -> str:
|
|
"""Get an API key from the environment — environment-only, by design.
|
|
|
|
``tooling/db/config.json`` is a *tracked* file and holds endpoints only;
|
|
it must never carry secrets, so there is deliberately no config.json
|
|
fallback here (the old one steered users toward committing paid API keys).
|
|
``config_key`` is retained in the signature for caller compatibility but
|
|
is ignored. Prints a JSON error and exits 1 if the variable is unset —
|
|
connector scripts emit machine-readable JSON on all paths.
|
|
"""
|
|
key = os.environ.get(env_var)
|
|
if key:
|
|
return key
|
|
print(json.dumps({
|
|
"ok": False,
|
|
"error": (
|
|
f"{env_var} not set. Export it in your shell or add it to the "
|
|
"machine-local .claude/settings.local.json env block (untracked). "
|
|
"Never put keys in tooling/db/config.json — it is tracked."
|
|
)
|
|
}, indent=2))
|
|
sys.exit(1)
|