Add Case Stage 5 owned repo planning

This commit is contained in:
Svrnty
2026-05-31 23:43:50 -04:00
parent ba0499802c
commit 51977d36cd
6 changed files with 256 additions and 0 deletions
+53
View File
@@ -32,6 +32,8 @@ REQUIRED_FILES = [
".sot/03-PROTOCOLS/CTO-CASE-STAGE3-COPIED-REPO-ISSUES.md",
".sot/03-PROTOCOLS/CTO-CASE-STAGE4-DISPOSABLE-SANDBOX-PRD.md",
".sot/03-PROTOCOLS/CTO-CASE-STAGE4-DISPOSABLE-SANDBOX-ISSUES.md",
".sot/03-PROTOCOLS/CTO-CASE-STAGE5-OWNED-NONCRITICAL-REPO-PRD.md",
".sot/03-PROTOCOLS/CTO-CASE-STAGE5-OWNED-NONCRITICAL-REPO-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",
@@ -313,6 +315,25 @@ REQUIRED_STAGE4_ISSUE_IDS = [
"CTO-WORK-036",
]
REQUIRED_STAGE5_PRD_PHRASES = [
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
"Stage 5 allowed mutation scope is `explicitly owned low-risk repository only`.",
"CTO_HARNESS_ALLOW_CASE=1",
"CTO_HARNESS_CASE_STAGE=5",
"Target Repository ownership proof and noncritical classification",
"approval requested/granted/denied events before mutation",
"allowed paths and forbidden actions before mutation",
"Operator acceptance or rejection is recorded after verification.",
"No push, merge, deploy, close, PR open, issue close, or public publication occurs by default.",
"approval denied, unowned repository, critical repository, disallowed file, dirty starting tree, dirty ending tree, failed tests, timeout, provider unavailable, and missing operator outcome",
"Stage 5 is successful when Case changes only approved paths inside an explicitly owned low-risk noncritical repository",
]
REQUIRED_STAGE5_ISSUE_IDS = [
"CTO-WORK-037",
"CTO-WORK-038",
]
REQUIRED_PROVIDER_ADMISSION_PRD_PHRASES = [
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
"https://github.com/workos/case.git",
@@ -953,6 +974,28 @@ def main() -> int:
if issue_id not in text:
errors.append(f"missing_stage4_issue_id:{issue_id}")
stage5_prd = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-STAGE5-OWNED-NONCRITICAL-REPO-PRD.md"
if stage5_prd.is_file():
text = stage5_prd.read_text(encoding="utf-8")
if "core_promotion_status: not-promoted" not in text:
errors.append("stage5_prd_missing_not_promoted_frontmatter")
for phrase in REQUIRED_STAGE5_PRD_PHRASES:
checked.append(f"stage5_prd_phrase:{phrase}")
if phrase not in text:
errors.append(f"missing_stage5_prd_phrase:{phrase}")
stage5_issues = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-STAGE5-OWNED-NONCRITICAL-REPO-ISSUES.md"
if stage5_issues.is_file():
text = stage5_issues.read_text(encoding="utf-8")
if "core_promotion_status: not-promoted" not in text:
errors.append("stage5_issues_missing_not_promoted_frontmatter")
if "Local planning SOT only. Not a Core Protocol. Not active Core authority." not in text:
errors.append("stage5_issues_missing_local_planning_notice")
for issue_id in REQUIRED_STAGE5_ISSUE_IDS:
checked.append(f"stage5_issue_id:{issue_id}")
if issue_id not in text:
errors.append(f"missing_stage5_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")
@@ -1152,6 +1195,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_STAGE5_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:
@@ -1205,6 +1252,8 @@ def main() -> int:
"CTO-WORK-034": "validated",
"CTO-WORK-035": "validated",
"CTO-WORK-036": "validated",
"CTO-WORK-037": "validated",
"CTO-WORK-038": "blocked",
}
for issue_id, expected in expected_statuses.items():
checked.append(f"workboard_status:{issue_id}:{expected}")
@@ -1239,6 +1288,10 @@ def main() -> int:
errors.append("workboard_missing_stage4_prd_source")
if "CTO-CASE-STAGE4-DISPOSABLE-SANDBOX-ISSUES.md" not in text:
errors.append("workboard_missing_stage4_issues_source")
if "CTO-CASE-STAGE5-OWNED-NONCRITICAL-REPO-PRD.md" not in text:
errors.append("workboard_missing_stage5_prd_source")
if "CTO-CASE-STAGE5-OWNED-NONCRITICAL-REPO-ISSUES.md" not in text:
errors.append("workboard_missing_stage5_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: