feat(awooop): expose apply gate closure readiness
This commit is contained in:
@@ -4079,6 +4079,7 @@ def _status_chain_ansible_apply_gate_handoff(
|
||||
*,
|
||||
ansible_dry_run_only: bool,
|
||||
execution_section: dict[str, Any],
|
||||
facts: dict[str, Any],
|
||||
incident_ids: list[str],
|
||||
source_id: str | None,
|
||||
verification: str,
|
||||
@@ -4121,6 +4122,64 @@ def _status_chain_ansible_apply_gate_handoff(
|
||||
latest_returncode = str(ansible.get("latest_returncode") or "")
|
||||
dry_run_passed = latest_status == "success" and latest_returncode in {"", "0"}
|
||||
verifier_ready = str(verification).lower() in {"verified", "success", "healthy"}
|
||||
mcp_evidence_ready = _safe_int(facts.get("mcp_gateway_total")) > 0
|
||||
closure_gates = [
|
||||
{
|
||||
"key": "mcp_evidence",
|
||||
"status": "passed" if mcp_evidence_ready else "warning",
|
||||
"detail": f"mcp={_safe_int(facts.get('mcp_gateway_total'))}",
|
||||
"asset_id": f"mcp-evidence:{safe_source_ref}",
|
||||
},
|
||||
{
|
||||
"key": "dry_run",
|
||||
"status": "passed" if dry_run_passed else "warning",
|
||||
"detail": (
|
||||
f"check={_safe_int(ansible.get('check_mode_total'))}; "
|
||||
f"rc={ansible.get('latest_returncode') if ansible.get('latest_returncode') is not None else '--'}"
|
||||
),
|
||||
"asset_id": f"ansible-check-mode:{catalog_id}",
|
||||
},
|
||||
{
|
||||
"key": "apply_candidate",
|
||||
"status": "passed",
|
||||
"detail": f"catalog={catalog_id}",
|
||||
"asset_id": f"ansible-apply-candidate:{catalog_id}",
|
||||
},
|
||||
{
|
||||
"key": "owner_release",
|
||||
"status": "blocked",
|
||||
"detail": "owner_release_receipt=0",
|
||||
"asset_id": f"owner-release-approval:{safe_source_ref}",
|
||||
},
|
||||
{
|
||||
"key": "controlled_execution",
|
||||
"status": "blocked",
|
||||
"detail": "runtime_gate=closed",
|
||||
"asset_id": f"controlled-execution:{safe_source_ref}",
|
||||
},
|
||||
{
|
||||
"key": "post_apply_verifier",
|
||||
"status": "blocked",
|
||||
"detail": f"verification={verification or 'missing'}",
|
||||
"asset_id": f"verifier-plan:{safe_source_ref}",
|
||||
},
|
||||
{
|
||||
"key": "km_writeback",
|
||||
"status": "blocked",
|
||||
"detail": f"km={_safe_int(facts.get('knowledge_entries'))}",
|
||||
"asset_id": f"km-writeback-candidate:{safe_source_ref}",
|
||||
},
|
||||
{
|
||||
"key": "playbook_trust",
|
||||
"status": "blocked",
|
||||
"detail": "trust_writeback=0",
|
||||
"asset_id": f"playbook-trust-update-candidate:{catalog_id}",
|
||||
},
|
||||
]
|
||||
closure_ready_count = sum(1 for gate in closure_gates if gate["status"] == "passed")
|
||||
closure_total_count = len(closure_gates)
|
||||
closure_blocked_count = sum(1 for gate in closure_gates if gate["status"] == "blocked")
|
||||
closure_completion_percent = int(round((closure_ready_count / closure_total_count) * 100))
|
||||
|
||||
return {
|
||||
"schema_version": "awooop_automation_handoff_v1",
|
||||
@@ -4138,6 +4197,54 @@ def _status_chain_ansible_apply_gate_handoff(
|
||||
"apply_candidate": f"ansible-apply-candidate:{catalog_id}",
|
||||
"verifier": f"verifier-plan:{safe_source_ref}",
|
||||
},
|
||||
"closure_readiness": {
|
||||
"schema_version": "awooop_apply_gate_closure_readiness_v1",
|
||||
"status": "blocked_before_owner_release",
|
||||
"completion_percent": closure_completion_percent,
|
||||
"ready_count": closure_ready_count,
|
||||
"total_count": closure_total_count,
|
||||
"blocked_count": closure_blocked_count,
|
||||
"runtime_execution_authorized": False,
|
||||
"writes_runtime_state": False,
|
||||
"next_action": "review_owner_release_packet_before_apply",
|
||||
"blocked_reason": (
|
||||
"owner_release_controlled_execution_verifier_km_playbook_trust_missing"
|
||||
),
|
||||
"gates": closure_gates,
|
||||
"required_owner_fields": [
|
||||
"owner_approval_receipt",
|
||||
"maintenance_window",
|
||||
"rollback_owner",
|
||||
"blast_radius",
|
||||
"post_apply_verifier_plan",
|
||||
"km_writeback_owner",
|
||||
"playbook_trust_writeback_owner",
|
||||
"evidence_refs",
|
||||
],
|
||||
"readback_assets": [
|
||||
{
|
||||
"key": "owner_execution_rehearsal",
|
||||
"asset_id": (
|
||||
"agent-result-capture-owner-approved-execution-rehearsal:P2-126"
|
||||
),
|
||||
"status": "no_write_rehearsal",
|
||||
},
|
||||
{
|
||||
"key": "final_candidate_readback",
|
||||
"asset_id": (
|
||||
"agent-result-capture-final-release-candidate-readback:P2-133"
|
||||
),
|
||||
"status": "read_only",
|
||||
},
|
||||
{
|
||||
"key": "release_verifier_preflight",
|
||||
"asset_id": (
|
||||
"agent-result-capture-release-verifier-preflight-gate:P2-136"
|
||||
),
|
||||
"status": "read_only",
|
||||
},
|
||||
],
|
||||
},
|
||||
"candidate": {
|
||||
"catalog_id": catalog_id,
|
||||
"check_mode_playbook_path": check_mode_playbook,
|
||||
@@ -5026,6 +5133,7 @@ def _build_awooop_status_chain(
|
||||
automation_handoff = _status_chain_ansible_apply_gate_handoff(
|
||||
ansible_dry_run_only=ansible_dry_run_only,
|
||||
execution_section=execution_section,
|
||||
facts=facts,
|
||||
incident_ids=incident_ids,
|
||||
source_id=source_id,
|
||||
verification=str(verification),
|
||||
|
||||
Reference in New Issue
Block a user