from __future__ import annotations import json from pathlib import Path import yaml ROOT = Path(__file__).resolve().parents[1] import sys if sys.stdout.encoding and sys.stdout.encoding.lower() not in ("utf-8", "utf8"): sys.stdout = open(sys.stdout.fileno(), mode="w", encoding="utf-8", buffering=1) def main() -> int: spec_path = ROOT / "spec" / "operating_cadence.yaml" if not spec_path.exists(): print(json.dumps({"formula_id": "OPERATING_CADENCE_V1", "gate": "FAIL", "error": f"spec not found: {spec_path}"})) return 1 spec = yaml.safe_load(spec_path.read_text(encoding="utf-8")) cadence = spec.get("cadence", {}) weekly = cadence.get("weekly_rebalance", {}) rebalance_days = weekly.get("days", []) weekend_rebalance_flag = "Saturday" in rebalance_days and "Sunday" in rebalance_days interim = cadence.get("interim_check", {}) monthly_midcheck_dates = sorted(interim.get("dates", [])) midcheck_ok = monthly_midcheck_dates == [1, 11, 21] # Cross-check against live signal artifact if available signal_path = ROOT / "Temp" / "operating_cadence_signal_v1.json" signal_status = "DATA_MISSING" if signal_path.exists(): sig = json.loads(signal_path.read_text(encoding="utf-8")) sig_id = sig.get("formula_id", "") if sig_id == "OPERATING_CADENCE_SIGNAL_V1": signal_status = "PRESENT" gate = "PASS" if weekend_rebalance_flag and midcheck_ok else "FAIL" result = { "formula_id": "OPERATING_CADENCE_V1", "weekend_rebalance_flag": weekend_rebalance_flag, "rebalance_days": rebalance_days, "monthly_midcheck_dates": monthly_midcheck_dates, "signal_artifact_status": signal_status, "gate": gate, } out = ROOT / "Temp" / "operating_cadence_v1.json" out.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") print(json.dumps(result, ensure_ascii=True, indent=2)) return 0 if gate == "PASS" else 1 if __name__ == "__main__": raise SystemExit(main())