315 lines
12 KiB
Python
315 lines
12 KiB
Python
#!/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",
|
|
"sot/03-PROTOCOLS/CTO-HARNESS-EVIDENCE-INTERFACE-CONTRACT.md",
|
|
"sot/03-PROTOCOLS/CTO-CASE-SOURCE-ADMISSION-RECORD.md",
|
|
"sot/03-PROTOCOLS/CTO-CASE-ADAPTER-CONTRACT.md",
|
|
"sot/03-PROTOCOLS/CTO-CASE-FAILURE-FIXTURE-MATRIX.md",
|
|
"sot/03-PROTOCOLS/CTO-CASE-STAGED-PROOF-GATES.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",
|
|
]
|
|
|
|
REQUIRED_EVIDENCE_INTERFACE_PHRASES = [
|
|
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
|
|
"This contract does not authorize Runtime behavior",
|
|
"The Harness Evidence Interface is the only accepted proof surface for backend comparison.",
|
|
"report.json",
|
|
"events.normalized.jsonl",
|
|
"patch.diff",
|
|
"test.log",
|
|
"trace.jsonl",
|
|
"artifact_digests",
|
|
"SHA-256",
|
|
"run_started_at",
|
|
"run_finished_at",
|
|
"backend_exit_code",
|
|
"allowed_writes_passed",
|
|
"approval.requested",
|
|
"approval.granted",
|
|
"approval.denied",
|
|
"Case may recommend. Case must not approve itself.",
|
|
"No merge, push, deploy, close, or real-repo mutation is allowed without explicit task-contract permission.",
|
|
"fail closed",
|
|
]
|
|
|
|
REQUIRED_SOURCE_ADMISSION_PHRASES = [
|
|
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
|
|
"This record does not authorize Runtime behavior",
|
|
"https://github.com/workos/case.git",
|
|
"7959ac917cdeb0983b4aaa20bb9f42021747fed8",
|
|
"2026-05-31",
|
|
"git clone --depth 1 https://github.com/workos/case.git",
|
|
"License status is unresolved.",
|
|
"package private: true",
|
|
"Status: not admitted for execution.",
|
|
"Current allowed execution mode: planning-only.",
|
|
"do not mutate the Case repository",
|
|
"do not vendor Case source into Cortex OS Core",
|
|
"No moving branch reference may be used as proof without a pinned commit or tag.",
|
|
]
|
|
|
|
REQUIRED_ADAPTER_CONTRACT_PHRASES = [
|
|
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
|
|
"This contract does not authorize Runtime behavior",
|
|
"register backend id `case` as a gated engine before execution",
|
|
"require the harness to accept `--engine case` only when explicitly enabled",
|
|
"prevent a parallel runner path outside the existing harness seam",
|
|
"`case` must be disabled by default.",
|
|
"No missing gate may degrade to a warning. Missing gate means blocked.",
|
|
"Adapter Input Contract",
|
|
"Adapter Output Contract",
|
|
"CTO Eligibility Decision",
|
|
"`selected_backend`",
|
|
"`denied_backends`",
|
|
"`required_gates`",
|
|
"`missing_gates`",
|
|
"`allowed_mutation_mode`",
|
|
"Case must not create or override the Eligibility Decision.",
|
|
"Case may recommend. Case must not approve itself or select its own authority.",
|
|
"This contract deliberately does not create `case-engine.sh`.",
|
|
]
|
|
|
|
REQUIRED_FAILURE_FIXTURE_PHRASES = [
|
|
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
|
|
"This matrix does not authorize Runtime behavior",
|
|
"This matrix is planning-only and does not run Case.",
|
|
"no-diff",
|
|
"disallowed-file",
|
|
"failed-tests",
|
|
"missing-test-command",
|
|
"missing-event",
|
|
"reviewer-reject",
|
|
"approval-denied",
|
|
"timeout",
|
|
"dirty-starting-tree",
|
|
"dirty-ending-tree",
|
|
"artifact-write-failure",
|
|
"provider-unavailable",
|
|
"`no_diff`",
|
|
"`disallowed_file_change`",
|
|
"`verification_failed`",
|
|
"`missing_test_command`",
|
|
"`missing_required_event`",
|
|
"`reviewer_rejected`",
|
|
"`approval_denied`",
|
|
"`dirty_starting_tree`",
|
|
"`dirty_ending_tree`",
|
|
"`artifact_write_failure`",
|
|
"`provider_unavailable`",
|
|
"report.json",
|
|
"events.normalized.jsonl",
|
|
"patch.diff",
|
|
"test.log",
|
|
"trace.jsonl",
|
|
"artifact_digests",
|
|
"freshness proof",
|
|
"fail closed",
|
|
]
|
|
|
|
REQUIRED_STAGED_PROOF_PHRASES = [
|
|
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
|
|
"Default status is earned, not assumed.",
|
|
"Stages must be completed in order.",
|
|
"Missing evidence means blocked, not partially accepted.",
|
|
"Stage 1 - Gated Case Engine",
|
|
"Stage 2 - Artificial Fixture",
|
|
"Stage 3 - Copied Repo Fixture",
|
|
"Stage 4 - Disposable Sandbox Repo",
|
|
"Stage 5 - Owned Noncritical Repo",
|
|
"Stage 6 - Candidate Default",
|
|
"Allowed mutation scope: none.",
|
|
"Allowed mutation scope: copied artificial case only.",
|
|
"Allowed mutation scope: copied local repository fixture only.",
|
|
"Allowed mutation scope: disposable repository only.",
|
|
"Allowed mutation scope: explicitly owned low-risk repository only.",
|
|
"Allowed mutation scope: scoped real-repo use only.",
|
|
"fake, Codex, and Pi where applicable",
|
|
"Case matches or beats existing lanes on report shape",
|
|
"Case matches or beats existing lanes on failure closure",
|
|
"Any future implementation must start with Stage 1",
|
|
"must not skip to real-repo execution",
|
|
]
|
|
|
|
|
|
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}")
|
|
|
|
evidence_interface = ROOT / "sot/03-PROTOCOLS/CTO-HARNESS-EVIDENCE-INTERFACE-CONTRACT.md"
|
|
if evidence_interface.is_file():
|
|
text = evidence_interface.read_text(encoding="utf-8")
|
|
if "core_promotion_status: not-promoted" not in text:
|
|
errors.append("evidence_interface_missing_not_promoted_frontmatter")
|
|
for phrase in REQUIRED_EVIDENCE_INTERFACE_PHRASES:
|
|
checked.append(f"evidence_interface_phrase:{phrase}")
|
|
if phrase not in text:
|
|
errors.append(f"missing_evidence_interface_phrase:{phrase}")
|
|
|
|
source_admission = ROOT / "sot/03-PROTOCOLS/CTO-CASE-SOURCE-ADMISSION-RECORD.md"
|
|
if source_admission.is_file():
|
|
text = source_admission.read_text(encoding="utf-8")
|
|
if "core_promotion_status: not-promoted" not in text:
|
|
errors.append("source_admission_missing_not_promoted_frontmatter")
|
|
for phrase in REQUIRED_SOURCE_ADMISSION_PHRASES:
|
|
checked.append(f"source_admission_phrase:{phrase}")
|
|
if phrase not in text:
|
|
errors.append(f"missing_source_admission_phrase:{phrase}")
|
|
|
|
adapter_contract = ROOT / "sot/03-PROTOCOLS/CTO-CASE-ADAPTER-CONTRACT.md"
|
|
if adapter_contract.is_file():
|
|
text = adapter_contract.read_text(encoding="utf-8")
|
|
if "core_promotion_status: not-promoted" not in text:
|
|
errors.append("adapter_contract_missing_not_promoted_frontmatter")
|
|
for phrase in REQUIRED_ADAPTER_CONTRACT_PHRASES:
|
|
checked.append(f"adapter_contract_phrase:{phrase}")
|
|
if phrase not in text:
|
|
errors.append(f"missing_adapter_contract_phrase:{phrase}")
|
|
|
|
failure_matrix = ROOT / "sot/03-PROTOCOLS/CTO-CASE-FAILURE-FIXTURE-MATRIX.md"
|
|
if failure_matrix.is_file():
|
|
text = failure_matrix.read_text(encoding="utf-8")
|
|
if "core_promotion_status: not-promoted" not in text:
|
|
errors.append("failure_matrix_missing_not_promoted_frontmatter")
|
|
for phrase in REQUIRED_FAILURE_FIXTURE_PHRASES:
|
|
checked.append(f"failure_matrix_phrase:{phrase}")
|
|
if phrase not in text:
|
|
errors.append(f"missing_failure_matrix_phrase:{phrase}")
|
|
|
|
staged_proof = ROOT / "sot/03-PROTOCOLS/CTO-CASE-STAGED-PROOF-GATES.md"
|
|
if staged_proof.is_file():
|
|
text = staged_proof.read_text(encoding="utf-8")
|
|
if "core_promotion_status: not-promoted" not in text:
|
|
errors.append("staged_proof_missing_not_promoted_frontmatter")
|
|
for phrase in REQUIRED_STAGED_PROOF_PHRASES:
|
|
checked.append(f"staged_proof_phrase:{phrase}")
|
|
if phrase not in text:
|
|
errors.append(f"missing_staged_proof_phrase:{phrase}")
|
|
|
|
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}")
|
|
if "CTO-HARNESS-EVIDENCE-INTERFACE-CONTRACT.md" not in text:
|
|
errors.append("workboard_missing_evidence_interface_contract_source")
|
|
if "CTO-WORK-004" in text and "status: validated" not in text:
|
|
errors.append("workboard_cto_work_004_not_validated")
|
|
if "CTO-CASE-SOURCE-ADMISSION-RECORD.md" not in text:
|
|
errors.append("workboard_missing_source_admission_record_source")
|
|
if "CTO-CASE-ADAPTER-CONTRACT.md" not in text:
|
|
errors.append("workboard_missing_adapter_contract_source")
|
|
if "CTO-CASE-FAILURE-FIXTURE-MATRIX.md" not in text:
|
|
errors.append("workboard_missing_failure_matrix_source")
|
|
if "CTO-CASE-STAGED-PROOF-GATES.md" not in text:
|
|
errors.append("workboard_missing_staged_proof_gates_source")
|
|
|
|
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())
|