diff --git a/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-ISSUES.md b/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-ISSUES.md new file mode 100644 index 0000000..c6e54de --- /dev/null +++ b/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-ISSUES.md @@ -0,0 +1,55 @@ +--- +name: CTO Hermes Approval Packet Issues +status: candidate +lifecycle_classification: sot +owner: jp +created: 2026-06-01 +last_reviewed: 2026-06-01 +core_promotion_status: not-promoted +--- + +# CTO Hermes Approval Packet Issues + +Local planning SOT only. Not a Core Protocol. Not active Core authority. + +## CTO-WORK-064: Hermes WebUI JP Approval Packet PRD + +Status: validated. + +Acceptance criteria: + +- PRD defines the JP approval packet scope. +- PRD keeps packet generation read-only. +- PRD includes `approval_packet`. +- PRD includes `approval_command_text`. +- PRD forbids executable approval buttons. +- PRD states Hermes prepares approval text; JP remains the approver. + +## CTO-WORK-065: Hermes WebUI JP Approval Packet Surface + +Status: candidate. + +Implementation route: + +- Add `approval_packet` to `/api/cto/control-summary`. +- Add `approval_command_text`. +- Add copy/paste approval packet text for JP. +- Include required evidence paths. +- Include allowed paths. +- Include blocked actions. +- Render copy/paste packet text in `cto_control_panel.js`. +- Add focused plugin tests. +- Record evidence after implementation. + +Acceptance criteria: + +- CTO control summary includes `approval_packet`. +- CTO control summary includes `approval_command_text`. +- CTO control summary includes required evidence paths. +- CTO control summary includes allowed paths. +- CTO control summary includes blocked actions. +- 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 prepares approval text; JP remains the approver. diff --git a/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-PRD.md b/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-PRD.md new file mode 100644 index 0000000..273aa08 --- /dev/null +++ b/.sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-PRD.md @@ -0,0 +1,63 @@ +--- +name: CTO Hermes Approval Packet PRD +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 PRD + +Local planning SOT only. Not a Core Protocol. Not active Core authority. + +## Problem + +Hermes now shows read-only JP approval state, but JP still needs a precise copy/paste approval packet that includes evidence paths, allowed paths, blocked actions, and the exact approval text. Without that, the handoff from proof to human approval is still manual and easy to distort. + +## Scope + +Add a read-only JP approval packet to the CTO control summary and panel: + +- `approval_packet` +- `approval_command_text` +- required evidence paths +- allowed paths +- blocked actions +- proof-ready state + +The packet prepares text for JP to copy/paste. It must not approve anything by itself. + +## Non-goals + +- Do not add executable approval buttons. +- Do not activate Case as default backend. +- Do not mutate target repositories. +- Do not edit upstream `hermes-webui`. +- Do not edit upstream `hermes-agent`. +- Do not change Cortex Core authority. +- Do not infer missing target repository admission beyond Harness evidence. + +## Acceptance Criteria + +- CTO control summary includes `approval_packet`. +- Approval packet includes `approval_command_text`. +- Approval packet includes required evidence paths. +- Approval packet includes allowed paths. +- Approval packet includes blocked actions. +- Approval packet is marked not executable. +- Hermes panel renders copy/paste approval text. +- Harness-backed summary data remains the source of truth. +- Hermes prepares approval text; JP remains the approver. + +## Validation + +- Focused plugin tests prove packet fields, fail-closed state, and static rendering hooks. +- Plugin aggregate tests pass before commit and after merge. +- CTO child validator records planning and evidence. +- S69 prose validator passes before report. + +## Success Definition + +Hermes can prepare a precise JP approval packet from Harness evidence without gaining approval authority or execution authority. diff --git a/WORKBOARD.yaml b/WORKBOARD.yaml index 56c1a7f..4b31c55 100644 --- a/WORKBOARD.yaml +++ b/WORKBOARD.yaml @@ -316,3 +316,13 @@ items: status: validated source: .sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-STATE-ISSUES.md owner: "" + - id: CTO-WORK-064 + title: Hermes WebUI JP Approval Packet PRD + status: validated + source: .sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-PRD.md + owner: "" + - id: CTO-WORK-065 + title: Hermes WebUI JP Approval Packet Surface + status: candidate + 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 92851bb..6444665 100644 --- a/tools/validate_cto_child.py +++ b/tools/validate_cto_child.py @@ -57,6 +57,8 @@ REQUIRED_FILES = [ ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-STATE-PRD.md", ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-STATE-ISSUES.md", ".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-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", @@ -241,6 +243,22 @@ REQUIRED_HERMES_APPROVAL_STATE_EVIDENCE_PHRASES = [ "upstream `hermes-agent` edited: false", ] +REQUIRED_HERMES_APPROVAL_PACKET_PHRASES = [ + "Local planning SOT only. Not a Core Protocol. Not active Core authority.", + "JP approval packet", + "copy/paste approval packet", + "approval_packet", + "approval_command_text", + "required evidence paths", + "allowed paths", + "blocked actions", + "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 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", @@ -1324,6 +1342,26 @@ def main() -> int: if phrase not in text: errors.append(f"missing_hermes_approval_state_evidence_phrase:{phrase}") + hermes_approval_packet_prd = ROOT / ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-PRD.md" + if hermes_approval_packet_prd.is_file(): + text = hermes_approval_packet_prd.read_text(encoding="utf-8") + if "core_promotion_status: not-promoted" not in text: + errors.append("hermes_approval_packet_prd_missing_not_promoted_frontmatter") + for phrase in REQUIRED_HERMES_APPROVAL_PACKET_PHRASES: + checked.append(f"hermes_approval_packet_prd_phrase:{phrase}") + if phrase not in text: + errors.append(f"missing_hermes_approval_packet_prd_phrase:{phrase}") + + hermes_approval_packet_issues = ROOT / ".sot/03-PROTOCOLS/CTO-HERMES-APPROVAL-PACKET-ISSUES.md" + if hermes_approval_packet_issues.is_file(): + text = hermes_approval_packet_issues.read_text(encoding="utf-8") + if "core_promotion_status: not-promoted" not in text: + errors.append("hermes_approval_packet_issues_missing_not_promoted_frontmatter") + for phrase in ["CTO-WORK-064", "CTO-WORK-065", *REQUIRED_HERMES_APPROVAL_PACKET_PHRASES]: + checked.append(f"hermes_approval_packet_issue_phrase:{phrase}") + if phrase not in text: + errors.append(f"missing_hermes_approval_packet_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") @@ -1938,6 +1976,8 @@ def main() -> int: "CTO-WORK-061": "validated", "CTO-WORK-062": "validated", "CTO-WORK-063": "validated", + "CTO-WORK-064": "validated", + "CTO-WORK-065": "candidate", } for issue_id, expected in expected_statuses.items(): checked.append(f"workboard_status:{issue_id}:{expected}")