#!/usr/bin/env python3 """Validate the child-local Cortex OS CTO workspace.""" from __future__ import annotations import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] REQUIRED_FILES = [ "AGENTS.md", "README.md", "WORKBOARD.yaml", "CONTEXT.md", "sot/00-START/CTO-WORKSPACE-INTENT.md", "sot/03-PROTOCOLS/CTO-CASE-BACKEND-BRIEF.md", "sot/03-PROTOCOLS/CTO-CASE-CANDIDATE-BACKEND-PRD.md", "sot/03-PROTOCOLS/CTO-CASE-CANDIDATE-BACKEND-ISSUES.md", ] REQUIRED_BRIEF_PHRASES = [ "Cortex governs.", "Hermes controls.", "Case executes.", "Harness proves.", "Core promotes only through SOT route.", "Case is the candidate CTO execution backend, not the CTO authority layer.", "This brief is child-local planning.", ] REQUIRED_PRD_PHRASES = [ "Local planning SOT only. Not a Core Protocol. Not active Core authority.", "Case Candidate Backend", "Harness Evidence Interface", "Case may recommend; CTO Harness records; Hermes or operator approval is the only human approval signal.", "Candidate Cortex Work Packet is an unpromoted term.", "Staged Proof Gates", "Source Admission Requirements", "Failure-Mode Matrix", "Fake remains the default validation lane.", ] FORBIDDEN_PRD_PHRASES = [ "Case should be the default real-repo execution backend", "Case is the default real-repo execution backend", ] REQUIRED_ISSUE_IDS = [ "CTO-WORK-003", "CTO-WORK-004", "CTO-WORK-005", "CTO-WORK-006", "CTO-WORK-007", "CTO-WORK-008", ] def main() -> int: checked: list[str] = [] errors: list[str] = [] for rel in REQUIRED_FILES: path = ROOT / rel checked.append(rel) if not path.is_file(): errors.append(f"missing_required_file:{rel}") brief = ROOT / "sot/03-PROTOCOLS/CTO-CASE-BACKEND-BRIEF.md" if brief.is_file(): text = brief.read_text(encoding="utf-8") for phrase in REQUIRED_BRIEF_PHRASES: checked.append(f"brief_phrase:{phrase}") if phrase not in text: errors.append(f"missing_brief_phrase:{phrase}") if "core_promotion_status: not-promoted" not in text: errors.append("brief_missing_not_promoted_frontmatter") prd = ROOT / "sot/03-PROTOCOLS/CTO-CASE-CANDIDATE-BACKEND-PRD.md" if prd.is_file(): text = prd.read_text(encoding="utf-8") for phrase in REQUIRED_PRD_PHRASES: checked.append(f"prd_phrase:{phrase}") if phrase not in text: errors.append(f"missing_prd_phrase:{phrase}") for phrase in FORBIDDEN_PRD_PHRASES: checked.append(f"prd_forbidden_phrase:{phrase}") if phrase in text: errors.append(f"forbidden_prd_phrase:{phrase}") if "core_promotion_status: not-promoted" not in text: errors.append("prd_missing_not_promoted_frontmatter") issues = ROOT / "sot/03-PROTOCOLS/CTO-CASE-CANDIDATE-BACKEND-ISSUES.md" if issues.is_file(): text = issues.read_text(encoding="utf-8") if "Local planning SOT only. Not a Core Protocol. Not active Core authority." not in text: errors.append("issues_missing_local_planning_notice") if "core_promotion_status: not-promoted" not in text: errors.append("issues_missing_not_promoted_frontmatter") for issue_id in REQUIRED_ISSUE_IDS: checked.append(f"issue_id:{issue_id}") if issue_id not in text: errors.append(f"missing_issue_id:{issue_id}") board = ROOT / "WORKBOARD.yaml" if board.is_file(): text = board.read_text(encoding="utf-8") for issue_id in ["CTO-WORK-002", *REQUIRED_ISSUE_IDS]: checked.append(f"workboard_id:{issue_id}") if issue_id not in text: errors.append(f"missing_workboard_id:{issue_id}") payload = { "ok": not errors, "validator": "cto-child-v1", "checked": checked, "errors": errors, "warnings": [], } print(json.dumps(payload, indent=2, sort_keys=True)) return 0 if not errors else 1 if __name__ == "__main__": raise SystemExit(main())