diff --git a/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-EVIDENCE.md b/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-EVIDENCE.md new file mode 100644 index 0000000..309a6ca --- /dev/null +++ b/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-EVIDENCE.md @@ -0,0 +1,57 @@ +--- +name: CTO Hermes Approval Packet Evidence +status: validated +lifecycle_classification: sot +owner: jp +created: 2026-06-01 +last_reviewed: 2026-06-01 +core_promotion_status: not-promoted +--- + +# CTO Hermes Approval Packet Evidence + +Local planning SOT only. Not a Core Protocol. Not active Core authority. + +## Scope + +This evidence closes `CTO-WORK-065`. + +The implementation adds a read-only JP approval packet to the Hermes WebUI CTO control panel. It prepares copy/paste approval text from Harness evidence but does not approve execution, activate Case, or mutate target repositories. + +## Implementation Evidence + +- Hermes plugin commit: `a109448 Add CTO approval packet surface` +- API field: `approval_packet` +- API field: `approval_command_text` +- API field: required evidence paths +- API field: allowed paths +- API field: blocked actions +- API invariant: not executable +- UI surface: `static/cto_control_panel.js` +- Route surface: `routes/cto_control_summary.py` + +## Validation Evidence + +- Focused validation: `python3 -m pytest tests/unit/test_cto_control_summary.py tests/unit/test_cto_control_panel_static.py -q` +- Focused result: `5 passed` +- Aggregate validation before commit: `python3 scripts/ast-connection-map.py --check` +- Aggregate result before commit: `CONNECTION-MAP.md is fresh` +- Aggregate validation before commit: `python3 -m pytest tests/ -q` +- Aggregate result before commit: `103 passed, 4 skipped` +- Aggregate validation after merge: `python3 scripts/ast-connection-map.py --check` +- Aggregate result after merge: `CONNECTION-MAP.md is fresh` +- Aggregate validation after merge: `python3 -m pytest tests/ -q` +- Aggregate result after merge: `107 passed` + +## Governance Evidence + +- Harness-backed summary data remains the source of truth. +- Hermes prepares approval text; JP remains the approver. +- Case runtime default active: false +- target repository mutation: false +- upstream `hermes-webui` edited: false +- upstream `hermes-agent` edited: false + +## Result + +`CTO-WORK-065` is validated because Hermes can now prepare a JP approval packet while remaining read-only and non-executable. diff --git a/WORKBOARD.yaml b/WORKBOARD.yaml index 4b31c55..a1dd379 100644 --- a/WORKBOARD.yaml +++ b/WORKBOARD.yaml @@ -323,6 +323,6 @@ items: owner: "" - id: CTO-WORK-065 title: Hermes WebUI JP Approval Packet Surface - status: candidate + status: validated source: .sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-ISSUES.md owner: "" diff --git a/tools/validate_cto_child.py b/tools/validate_cto_child.py index 6444665..c69c0cd 100644 --- a/tools/validate_cto_child.py +++ b/tools/validate_cto_child.py @@ -59,6 +59,7 @@ REQUIRED_FILES = [ ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-STATE-EVIDENCE.md", ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-PRD.md", ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-ISSUES.md", + ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-EVIDENCE.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", @@ -259,6 +260,24 @@ REQUIRED_HERMES_APPROVAL_PACKET_PHRASES = [ "Hermes prepares approval text; JP remains the approver.", ] +REQUIRED_HERMES_APPROVAL_PACKET_EVIDENCE_PHRASES = [ + "Local planning SOT only. Not a Core Protocol. Not active Core authority.", + "CTO-WORK-065", + "a109448 Add CTO approval packet surface", + "approval_packet", + "approval_command_text", + "required evidence paths", + "allowed paths", + "blocked actions", + "not executable", + "5 passed", + "107 passed", + "CONNECTION-MAP.md is fresh", + "Case runtime default active: false", + "target repository mutation: false", + "Hermes prepares approval text; JP remains the approver.", +] + REQUIRED_HERMES_REAL_REFRESH_CONTROL_REPLAY_EVIDENCE_PHRASES = [ "Local planning SOT only. Not a Core Protocol. Not active Core authority.", "CTO-WORK-057", @@ -1362,6 +1381,16 @@ def main() -> int: if phrase not in text: errors.append(f"missing_hermes_approval_packet_issue_phrase:{phrase}") + hermes_approval_packet_evidence = ROOT / ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-EVIDENCE.md" + if hermes_approval_packet_evidence.is_file(): + text = hermes_approval_packet_evidence.read_text(encoding="utf-8") + if "core_promotion_status: not-promoted" not in text: + errors.append("hermes_approval_packet_evidence_missing_not_promoted_frontmatter") + for phrase in REQUIRED_HERMES_APPROVAL_PACKET_EVIDENCE_PHRASES: + checked.append(f"hermes_approval_packet_evidence_phrase:{phrase}") + if phrase not in text: + errors.append(f"missing_hermes_approval_packet_evidence_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") @@ -1977,7 +2006,7 @@ def main() -> int: "CTO-WORK-062": "validated", "CTO-WORK-063": "validated", "CTO-WORK-064": "validated", - "CTO-WORK-065": "candidate", + "CTO-WORK-065": "validated", } for issue_id, expected in expected_statuses.items(): checked.append(f"workboard_status:{issue_id}:{expected}")