Add Case Stage 6 candidate default planning

This commit is contained in:
Svrnty
2026-06-01 06:10:15 -04:00
parent 0116ed2ec3
commit 0996df1bf9
6 changed files with 265 additions and 0 deletions
+57
View File
@@ -36,6 +36,8 @@ REQUIRED_FILES = [
".sot/03-PROTOCOLS/CTO-CASE-STAGE5-OWNED-NONCRITICAL-REPO-ISSUES.md",
".sot/03-PROTOCOLS/CTO-CASE-STAGE5-TARGET-REPOSITORY-ADMISSION-TEMPLATE.md",
".sot/03-PROTOCOLS/CTO-CASE-STAGE5-TARGET-REPOSITORY-ADMISSION.json",
".sot/03-PROTOCOLS/CTO-CASE-STAGE6-CANDIDATE-DEFAULT-PRD.md",
".sot/03-PROTOCOLS/CTO-CASE-STAGE6-CANDIDATE-DEFAULT-ISSUES.md",
".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md",
".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-ISSUES.md",
".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-BUILD-PRD.md",
@@ -339,6 +341,29 @@ REQUIRED_STAGE5_ISSUE_IDS = [
"CTO-WORK-041",
]
REQUIRED_STAGE6_PRD_PHRASES = [
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
"Stage 6 allowed mutation scope is `scoped real-repo use only`.",
"Stage 5 validation before Stage 6",
"fake, Codex, and Pi where applicable",
"Harness Evidence Interface, not raw backend logs alone",
"report shape",
"event validity",
"allowed-path compliance",
"failure closure",
"artifact completeness",
"Case source admission freshness",
"Failure matrix rows are covered or explicitly blocked with rationale.",
"Operator acceptance is recorded after comparison proof.",
"Do not make Case the default backend.",
"Stage 6 is successful when the CTO Product Surface can record Case as a candidate-default backend only after Harness comparison evidence proves Case matches or beats fake, Codex, and Pi where applicable",
]
REQUIRED_STAGE6_ISSUE_IDS = [
"CTO-WORK-042",
"CTO-WORK-043",
]
REQUIRED_STAGE5_TARGET_ADMISSION_TEMPLATE_PHRASES = [
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
"This artifact is a template only. No Target Repository is admitted by this file.",
@@ -1093,6 +1118,28 @@ def main() -> int:
if key.lower() in {"api_key", "apikey", "access_token", "token", "secret", "password", "credential_value"}:
errors.append(f"stage5_target_admission_forbidden_secret_key:{key}")
stage6_prd = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-STAGE6-CANDIDATE-DEFAULT-PRD.md"
if stage6_prd.is_file():
text = stage6_prd.read_text(encoding="utf-8")
if "core_promotion_status: not-promoted" not in text:
errors.append("stage6_prd_missing_not_promoted_frontmatter")
for phrase in REQUIRED_STAGE6_PRD_PHRASES:
checked.append(f"stage6_prd_phrase:{phrase}")
if phrase not in text:
errors.append(f"missing_stage6_prd_phrase:{phrase}")
stage6_issues = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-STAGE6-CANDIDATE-DEFAULT-ISSUES.md"
if stage6_issues.is_file():
text = stage6_issues.read_text(encoding="utf-8")
if "core_promotion_status: not-promoted" not in text:
errors.append("stage6_issues_missing_not_promoted_frontmatter")
if "Local planning SOT only. Not a Core Protocol. Not active Core authority." not in text:
errors.append("stage6_issues_missing_local_planning_notice")
for issue_id in REQUIRED_STAGE6_ISSUE_IDS:
checked.append(f"stage6_issue_id:{issue_id}")
if issue_id not in text:
errors.append(f"missing_stage6_issue_id:{issue_id}")
provider_admission_prd = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md"
if provider_admission_prd.is_file():
text = provider_admission_prd.read_text(encoding="utf-8")
@@ -1296,6 +1343,10 @@ def main() -> int:
checked.append(f"workboard_id:{issue_id}")
if issue_id not in text:
errors.append(f"missing_workboard_id:{issue_id}")
for issue_id in REQUIRED_STAGE6_ISSUE_IDS:
checked.append(f"workboard_id:{issue_id}")
if issue_id not in text:
errors.append(f"missing_workboard_id:{issue_id}")
for issue_id in REQUIRED_PROVIDER_ADMISSION_ISSUE_IDS:
checked.append(f"workboard_id:{issue_id}")
if issue_id not in text:
@@ -1354,6 +1405,8 @@ def main() -> int:
"CTO-WORK-039": "validated",
"CTO-WORK-040": "validated",
"CTO-WORK-041": "validated",
"CTO-WORK-042": "validated",
"CTO-WORK-043": "candidate",
}
for issue_id, expected in expected_statuses.items():
checked.append(f"workboard_status:{issue_id}:{expected}")
@@ -1396,6 +1449,10 @@ def main() -> int:
errors.append("workboard_missing_stage5_target_admission_template_source")
if "CTO-CASE-STAGE5-TARGET-REPOSITORY-ADMISSION.json" not in text:
errors.append("workboard_missing_stage5_target_admission_json_source")
if "CTO-CASE-STAGE6-CANDIDATE-DEFAULT-PRD.md" not in text:
errors.append("workboard_missing_stage6_prd_source")
if "CTO-CASE-STAGE6-CANDIDATE-DEFAULT-ISSUES.md" not in text:
errors.append("workboard_missing_stage6_issues_source")
if "CTO-CASE-PROVIDER-ADMISSION-PRD.md" not in text:
errors.append("workboard_missing_provider_admission_prd_source")
if "CTO-CASE-PROVIDER-ADMISSION-ISSUES.md" not in text: