#!/usr/bin/env bash set -euo pipefail usage() { cat >&2 <<'EOF' Usage: OPERATOR_SAMPLE_MANIFEST_PATH=storage/operator-data/operator_samples_manifest.json \ QUALITY_MODEL_ASSET_IDS="geointel-building-yolov8s-aoi1024bg512r3e50-pt" \ QUALITY_THRESHOLDS="0.35 0.15" \ bash scripts/run_background_corpus_split_matrix.sh [base_url] Optional environment: BACKGROUND_SPLIT_OUTPUT_DIR Output directory, default: artifacts/detection-hard-negatives/background-split/. OPERATOR_SAMPLE_MANIFEST_PATH Manifest from prepare_operator_real_data_samples.py. OPERATOR_BACKGROUND_SAMPLE_SLUGS Optional comma/space separated slug filter applied to both categories. QUALITY_MODEL_ASSET_IDS Forwarded to run_operator_hard_negative_detection_matrix.sh. QUALITY_TILE_SIZES Forwarded to run_operator_hard_negative_detection_matrix.sh. QUALITY_TILE_OVERLAPS Forwarded to run_operator_hard_negative_detection_matrix.sh. QUALITY_THRESHOLDS Forwarded to run_operator_hard_negative_detection_matrix.sh. Runs two live hard-negative matrices from the same manifest: 1. pure_empty_negative: strict default-promotion false-positive gate. 2. sparse_building_context: review-only contextual evidence. The script does not upload reference vectors, run QA/QC, use fixture detections, fetch providers, download model weights or promote model defaults. EOF } ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" BASE_URL="${1:-${GE_INTEL_BASE_URL:-http://localhost:1202}}" BACKGROUND_SPLIT_OUTPUT_DIR="${BACKGROUND_SPLIT_OUTPUT_DIR:-artifacts/detection-hard-negatives/background-split/$(date -u +%Y%m%dT%H%M%SZ)}" if [ "${BASE_URL}" = "-h" ] || [ "${BASE_URL}" = "--help" ]; then usage exit 0 fi if [ -n "${PYTHON_BIN:-}" ]; then PYTHON_BIN="${PYTHON_BIN}" else PYTHON_BIN="" for candidate in python3 python.exe python; do if command -v "${candidate}" >/dev/null 2>&1 && "${candidate}" -c "import json, sys" >/dev/null 2>&1; then PYTHON_BIN="${candidate}" break fi done fi if [ -z "${PYTHON_BIN}" ]; then echo "A Python interpreter is required for background split reporting" >&2 exit 1 fi mkdir -p "${BACKGROUND_SPLIT_OUTPUT_DIR}" pure_output="${BACKGROUND_SPLIT_OUTPUT_DIR}/pure_empty_negative" sparse_output="${BACKGROUND_SPLIT_OUTPUT_DIR}/sparse_building_context" echo "== GeoIntel background corpus split matrix ==" echo "Base URL: ${BASE_URL}" echo "Output: ${BACKGROUND_SPLIT_OUTPUT_DIR}" echo "-- Running strict pure-empty default gate --" OPERATOR_BACKGROUND_CATEGORIES="pure_empty_negative" \ HARD_NEGATIVE_OUTPUT_DIR="${pure_output}" \ bash scripts/run_operator_hard_negative_detection_matrix.sh "${BASE_URL}" echo "-- Running sparse-context review matrix --" OPERATOR_BACKGROUND_CATEGORIES="sparse_building_context" \ HARD_NEGATIVE_OUTPUT_DIR="${sparse_output}" \ bash scripts/run_operator_hard_negative_detection_matrix.sh "${BASE_URL}" "${PYTHON_BIN}" scripts/build_background_corpus_split_report.py \ --pure-empty-summary "${pure_output}/hard_negative_matrix_summary.json" \ --sparse-context-summary "${sparse_output}/hard_negative_matrix_summary.json" \ --output-dir "${BACKGROUND_SPLIT_OUTPUT_DIR}" echo "Background corpus split summary: ${BACKGROUND_SPLIT_OUTPUT_DIR}/background_corpus_split_summary.json"