#!/bin/bash # Build the jobbsok Python environment and pin the ingestion guard. # # bash 3.2-clean and ASCII-only on purpose: the system bash on this Mac is 3.2, # and a multibyte character has crashed a `set -u` script here before. # # Where the environment lives is load-bearing, not incidental. When # CLAUDE_PLUGIN_DATA is set the environment is built there, because that # directory survives a plugin update -- the plugin's own cache does not. A # repo-root-only .venv would leave every non-development install without the # guard, which is risk H2. The repo-root .venv is the development case. # # Usage: # bash scripts/bootstrap.sh # dev dependencies # bash scripts/bootstrap.sh --med-xlsx # also the openpyxl extra set -eu MIN_MAJOR=3 MIN_MINOR=10 WITH_XLSX=0 for arg in "$@"; do case "$arg" in --med-xlsx) WITH_XLSX=1 ;; -h|--help) sed -n '2,20p' "$0" exit 0 ;; *) echo "bootstrap: unknown argument: $arg" >&2 echo "bootstrap: usage: bash scripts/bootstrap.sh [--med-xlsx]" >&2 exit 2 ;; esac done SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) REPO_ROOT=$(cd "$SCRIPT_DIR/.." && pwd) if [ -n "${CLAUDE_PLUGIN_DATA:-}" ]; then VENV_DIR="${CLAUDE_PLUGIN_DATA}/venv" VENV_KIND="plugin-data (survives a plugin update)" else VENV_DIR="${REPO_ROOT}/.venv" VENV_KIND="repo root (development)" fi # Refuse an interpreter that is too old rather than building an environment # that parses everything and fails at runtime. Under a GUI-spawned process with # an empty PATH, python3 here can resolve to 3.9.6. PYTHON_BIN="${JOBBSOK_PYTHON:-python3}" if ! command -v "$PYTHON_BIN" >/dev/null 2>&1; then echo "bootstrap: no such interpreter: $PYTHON_BIN" >&2 echo "bootstrap: set JOBBSOK_PYTHON to a Python ${MIN_MAJOR}.${MIN_MINOR}+ executable." >&2 exit 1 fi if ! "$PYTHON_BIN" -c "import sys; sys.exit(0 if sys.version_info >= ($MIN_MAJOR, $MIN_MINOR) else 1)"; then FOUND=$("$PYTHON_BIN" -c "import sys; print('%d.%d.%d' % sys.version_info[:3])") echo "bootstrap: $PYTHON_BIN is Python $FOUND; ${MIN_MAJOR}.${MIN_MINOR}+ is required." >&2 echo "bootstrap: refusing to build an environment on it. Set JOBBSOK_PYTHON instead." >&2 exit 1 fi echo "bootstrap: interpreter $("$PYTHON_BIN" -c 'import sys; print(sys.executable)')" echo "bootstrap: environment $VENV_DIR [$VENV_KIND]" if [ ! -x "${VENV_DIR}/bin/python" ]; then mkdir -p "$(dirname "$VENV_DIR")" "$PYTHON_BIN" -m venv "$VENV_DIR" fi VENV_PY="${VENV_DIR}/bin/python" "$VENV_PY" -m pip install --quiet --upgrade pip # PEP 735 dependency groups need pip 25.1+; the upgrade above is what makes # this line safe, and a pip too old to understand --group fails loudly here. "$VENV_PY" -m pip install --quiet --group "${REPO_ROOT}/pyproject.toml:dev" if [ "$WITH_XLSX" -eq 1 ]; then "$VENV_PY" -m pip install --quiet --group "${REPO_ROOT}/pyproject.toml:xlsx" fi "$VENV_PY" - <<'PYEOF' import sys import llm_ingestion_guard print("bootstrap: sys.executable %s" % sys.executable) print("bootstrap: python %s" % sys.version.split()[0]) print("bootstrap: guard %s" % llm_ingestion_guard.__version__) PYEOF echo "bootstrap: ok"