Add Hermes control surface planning

This commit is contained in:
Svrnty
2026-06-01 06:20:44 -04:00
parent f8f28e00fc
commit e759527955
6 changed files with 237 additions and 0 deletions
+53
View File
@@ -38,6 +38,8 @@ REQUIRED_FILES = [
".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-HERMES-CONTROL-SURFACE-PRD.md",
".sot/03-PROTOCOLS/CTO-HERMES-CONTROL-SURFACE-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",
@@ -364,6 +366,25 @@ REQUIRED_STAGE6_ISSUE_IDS = [
"CTO-WORK-043",
]
REQUIRED_HERMES_CONTROL_SURFACE_PRD_PHRASES = [
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
"Hermes controls visibility, approval, and replay but does not govern.",
"Harness Evidence Interface artifacts",
"proof ladder status through Stage 6",
"candidate-default eligibility separately from runtime default activation",
"replay paths for matrix and Stage 6 comparison evidence",
"blocked comparison lanes to include rationale",
"Do not build a full Hermes WebUI panel in this slice.",
"Do not activate Case as default backend.",
"Do not store secrets, endpoints, or credential values in reports.",
"This slice succeeds when Hermes can consume one Harness-generated summary",
]
REQUIRED_HERMES_CONTROL_SURFACE_ISSUE_IDS = [
"CTO-WORK-044",
"CTO-WORK-045",
]
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.",
@@ -1140,6 +1161,28 @@ def main() -> int:
if issue_id not in text:
errors.append(f"missing_stage6_issue_id:{issue_id}")
hermes_control_surface_prd = ROOT / ".sot/03-PROTOCOLS/CTO-HERMES-CONTROL-SURFACE-PRD.md"
if hermes_control_surface_prd.is_file():
text = hermes_control_surface_prd.read_text(encoding="utf-8")
if "core_promotion_status: not-promoted" not in text:
errors.append("hermes_control_surface_prd_missing_not_promoted_frontmatter")
for phrase in REQUIRED_HERMES_CONTROL_SURFACE_PRD_PHRASES:
checked.append(f"hermes_control_surface_prd_phrase:{phrase}")
if phrase not in text:
errors.append(f"missing_hermes_control_surface_prd_phrase:{phrase}")
hermes_control_surface_issues = ROOT / ".sot/03-PROTOCOLS/CTO-HERMES-CONTROL-SURFACE-ISSUES.md"
if hermes_control_surface_issues.is_file():
text = hermes_control_surface_issues.read_text(encoding="utf-8")
if "core_promotion_status: not-promoted" not in text:
errors.append("hermes_control_surface_issues_missing_not_promoted_frontmatter")
if "Local planning SOT only. Not a Core Protocol. Not active Core authority." not in text:
errors.append("hermes_control_surface_issues_missing_local_planning_notice")
for issue_id in REQUIRED_HERMES_CONTROL_SURFACE_ISSUE_IDS:
checked.append(f"hermes_control_surface_issue_id:{issue_id}")
if issue_id not in text:
errors.append(f"missing_hermes_control_surface_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")
@@ -1347,6 +1390,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_HERMES_CONTROL_SURFACE_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:
@@ -1407,6 +1454,8 @@ def main() -> int:
"CTO-WORK-041": "validated",
"CTO-WORK-042": "validated",
"CTO-WORK-043": "validated",
"CTO-WORK-044": "validated",
"CTO-WORK-045": "candidate",
}
for issue_id, expected in expected_statuses.items():
checked.append(f"workboard_status:{issue_id}:{expected}")
@@ -1453,6 +1502,10 @@ def main() -> int:
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-HERMES-CONTROL-SURFACE-PRD.md" not in text:
errors.append("workboard_missing_hermes_control_surface_prd_source")
if "CTO-HERMES-CONTROL-SURFACE-ISSUES.md" not in text:
errors.append("workboard_missing_hermes_control_surface_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: