Plan Hermes approval state

This commit is contained in:
Svrnty
2026-06-01 07:40:37 -04:00
parent e732e1f373
commit 405ea616a5
4 changed files with 162 additions and 0 deletions
+39
View File
@@ -54,6 +54,8 @@ REQUIRED_FILES = [
".sot/03-PROTOCOLS/CTO-HERMES-WEBUI-LIVE-SMOKE-PRD.md",
".sot/03-PROTOCOLS/CTO-HERMES-WEBUI-LIVE-SMOKE-ISSUES.md",
".sot/03-PROTOCOLS/CTO-HERMES-WEBUI-LIVE-SMOKE-EVIDENCE.md",
".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-STATE-PRD.md",
".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-STATE-ISSUES.md",
".sot/03-PROTOCOLS/CTO-FIRST-REAL-GOVERNED-WORKFLOW-PRD.md",
".sot/03-PROTOCOLS/CTO-FIRST-REAL-GOVERNED-WORKFLOW-ISSUES.md",
".sot/03-PROTOCOLS/CTO-FIRST-REAL-GOVERNED-WORKFLOW-APPROVAL-PACKET.md",
@@ -205,6 +207,21 @@ REQUIRED_HERMES_WEBUI_LIVE_SMOKE_EVIDENCE_PHRASES = [
"upstream `hermes-agent` edited: false",
]
REQUIRED_HERMES_APPROVAL_STATE_PHRASES = [
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
"JP approval state",
"read-only approval posture",
"allowed next actions",
"approval_required",
"approval_granted",
"execution_allowed",
"Do not add executable approval buttons.",
"Do not activate Case as default backend.",
"Do not mutate target repositories.",
"Harness-backed summary data remains the source of truth.",
"Hermes visualizes control state; CTO and Harness remain the gates.",
]
REQUIRED_HERMES_REAL_REFRESH_CONTROL_REPLAY_EVIDENCE_PHRASES = [
"Local planning SOT only. Not a Core Protocol. Not active Core authority.",
"CTO-WORK-057",
@@ -1258,6 +1275,26 @@ def main() -> int:
if phrase not in text:
errors.append(f"missing_hermes_webui_live_smoke_evidence_phrase:{phrase}")
hermes_approval_state_prd = ROOT / ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-STATE-PRD.md"
if hermes_approval_state_prd.is_file():
text = hermes_approval_state_prd.read_text(encoding="utf-8")
if "core_promotion_status: not-promoted" not in text:
errors.append("hermes_approval_state_prd_missing_not_promoted_frontmatter")
for phrase in REQUIRED_HERMES_APPROVAL_STATE_PHRASES:
checked.append(f"hermes_approval_state_prd_phrase:{phrase}")
if phrase not in text:
errors.append(f"missing_hermes_approval_state_prd_phrase:{phrase}")
hermes_approval_state_issues = ROOT / ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-STATE-ISSUES.md"
if hermes_approval_state_issues.is_file():
text = hermes_approval_state_issues.read_text(encoding="utf-8")
if "core_promotion_status: not-promoted" not in text:
errors.append("hermes_approval_state_issues_missing_not_promoted_frontmatter")
for phrase in ["CTO-WORK-062", "CTO-WORK-063", *REQUIRED_HERMES_APPROVAL_STATE_PHRASES]:
checked.append(f"hermes_approval_state_issue_phrase:{phrase}")
if phrase not in text:
errors.append(f"missing_hermes_approval_state_issue_phrase:{phrase}")
hermes_real_refresh_control_replay_evidence = ROOT / ".sot/03-PROTOCOLS/CTO-HERMES-REAL-REFRESH-CONTROL-REPLAY-EVIDENCE.md"
if hermes_real_refresh_control_replay_evidence.is_file():
text = hermes_real_refresh_control_replay_evidence.read_text(encoding="utf-8")
@@ -1870,6 +1907,8 @@ def main() -> int:
"CTO-WORK-059": "validated",
"CTO-WORK-060": "validated",
"CTO-WORK-061": "validated",
"CTO-WORK-062": "validated",
"CTO-WORK-063": "candidate",
}
for issue_id, expected in expected_statuses.items():
checked.append(f"workboard_status:{issue_id}:{expected}")