from __future__ import annotations import argparse import json from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[1] DEFAULT_PATH = ROOT / "Temp" / "strategy_harness_v2.json" def load_json(path: Path) -> dict[str, Any]: payload = json.loads(path.read_text(encoding="utf-8")) if not isinstance(payload, dict): raise ValueError("payload must be object") return payload def main() -> int: parser = argparse.ArgumentParser(description="Validate strategy harness v2 artifact") parser.add_argument("--json", default=str(DEFAULT_PATH)) args = parser.parse_args() path = Path(args.json) if not path.is_absolute(): path = ROOT / path payload = load_json(path) errors: list[str] = [] if not str(payload.get("schema_version") or "").startswith("2026-05-22-strategy-harness-v2"): errors.append("schema_version mismatch") for key in ( "buy_anti_late_chase_harness_v2", "sell_value_preserve_harness_v2", "cash_raise_optimizer_harness_v2", ): rows = payload.get(key) if not isinstance(rows, list): errors.append(f"{key} must be list") continue for i, row in enumerate(rows): if not isinstance(row, dict): errors.append(f"{key}[{i}] must be object") continue if not str(row.get("ticker") or "").strip(): errors.append(f"{key}[{i}].ticker missing") if errors: print("STRATEGY_HARNESS_V2_INVALID") print(json.dumps({"errors": errors}, ensure_ascii=False, indent=2)) return 1 print("STRATEGY_HARNESS_V2_OK") return 0 if __name__ == "__main__": raise SystemExit(main())