from __future__ import annotations import json import os import shlex import subprocess from pathlib import Path ROOT = Path(__file__).resolve().parents[2] def _bash_path(path: Path) -> str: raw_path = str(path) if os.name != "nt": return raw_path # ``bash`` is WSL on the supported Windows development path. Converting # the drive path directly avoids starting a second WSL process merely to # run ``wslpath``; that process can time out while the full suite is busy # and would leave curl with an invalid file://C:\\... URL. drive, tail = os.path.splitdrive(raw_path) if drive: normalized_tail = tail.lstrip("\\/").replace("\\", "/") return f"/mnt/{drive[0].lower()}/{normalized_tail}" return raw_path.replace("\\", "/") def test_split_background_promotion_workflow_runs_split_then_split_aware_report() -> None: script_path = ROOT / "scripts" / "run_split_background_promotion_workflow.sh" assert script_path.exists() source = script_path.read_text(encoding="utf-8") assert "run_background_corpus_split_matrix.sh" in source assert "build_detection_model_promotion_report.py" in source assert "--background-split-summary" in source assert "background_corpus_split_summary.json" in source assert "PROMOTION_POSITIVE_PORTFOLIO_PATH" in source assert "BACKGROUND_SPLIT_OUTPUT_DIR" in source assert "PROMOTION_OUTPUT_DIR" in source assert "--hard-negative-summary" not in source assert "download model" not in source.lower() assert "promote model default" not in source.lower() def test_split_background_promotion_workflow_has_safe_preflight_mode() -> None: source = (ROOT / "scripts" / "run_split_background_promotion_workflow.sh").read_text(encoding="utf-8") assert "--preflight-only" in source assert "PREFLIGHT_ONLY" in source assert "curl -fsS" in source assert "OPERATOR_SAMPLE_MANIFEST_PATH is required" in source assert "pure_empty_negative" in source assert "sparse_building_context" in source assert "Split-background promotion preflight passed" in source def test_split_background_preflight_derives_missing_background_categories(tmp_path: Path) -> None: positive_portfolio = tmp_path / "positive.json" positive_portfolio.write_text('{"items":[]}', encoding="utf-8") manifest = tmp_path / "operator_samples_manifest.json" manifest.write_text( json.dumps( { "samples": [ { "sample_slug": "postel_bos", "sample_role": "background_candidate", "reference_feature_count": 0, }, { "sample_slug": "kasterlee_bos", "sample_role": "background_candidate", "reference_feature_count": 7, }, ] } ), encoding="utf-8", ) api_root = tmp_path / "api-root" projects_endpoint = api_root / "api" / "v1" / "projects" projects_endpoint.parent.mkdir(parents=True) projects_endpoint.write_text('{"data":{"items":[]}}', encoding="utf-8") command = ( f"PROMOTION_POSITIVE_PORTFOLIO_PATH={shlex.quote(_bash_path(positive_portfolio))} " f"OPERATOR_SAMPLE_MANIFEST_PATH={shlex.quote(_bash_path(manifest))} " f"bash scripts/run_split_background_promotion_workflow.sh --preflight-only " f"{shlex.quote(f'file://{_bash_path(api_root)}')}" ) result = subprocess.run( ["bash", "-lc", command], cwd=ROOT, capture_output=True, text=True, timeout=30, check=False, ) assert result.returncode == 0, result.stderr assert "Split-background promotion preflight passed" in result.stdout def test_readiness_checks_split_background_promotion_workflow_syntax() -> None: readiness = (ROOT / "scripts" / "run_readiness_check.sh").read_text(encoding="utf-8") assert "bash -n scripts/run_split_background_promotion_workflow.sh" in readiness