feat(awooop): surface owner release closure tasks
This commit is contained in:
@@ -47,6 +47,12 @@ from src.services.awooop_truth_chain_service import (
|
||||
_summarize_mcp,
|
||||
fetch_truth_chain,
|
||||
)
|
||||
from src.services.ai_agent_result_capture_owner_release_approval_gate import (
|
||||
load_latest_ai_agent_result_capture_owner_release_approval_gate,
|
||||
)
|
||||
from src.services.ai_agent_result_capture_release_verifier_preflight_gate import (
|
||||
load_latest_ai_agent_result_capture_release_verifier_preflight_gate,
|
||||
)
|
||||
from src.services.governance_km_stale_review_service import (
|
||||
query_km_stale_owner_review_completion_queue,
|
||||
)
|
||||
@@ -4075,6 +4081,217 @@ def _status_chain_ansible_dry_run_only(
|
||||
)
|
||||
|
||||
|
||||
def _compact_release_items(
|
||||
items: Any,
|
||||
*,
|
||||
id_field: str,
|
||||
summary_field: str,
|
||||
limit: int = 5,
|
||||
) -> list[dict[str, Any]]:
|
||||
if not isinstance(items, list):
|
||||
return []
|
||||
compacted: list[dict[str, Any]] = []
|
||||
for item in items:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
compacted.append(
|
||||
{
|
||||
"id": item.get(id_field),
|
||||
"display_name": item.get("display_name"),
|
||||
"owner_agent": item.get("owner_agent"),
|
||||
"status": item.get("status"),
|
||||
"summary": item.get(summary_field),
|
||||
"runtime_write_allowed": item.get("runtime_write_allowed", False),
|
||||
}
|
||||
)
|
||||
if len(compacted) >= limit:
|
||||
break
|
||||
return compacted
|
||||
|
||||
|
||||
def _owner_release_package_bridge() -> dict[str, Any]:
|
||||
try:
|
||||
payload = load_latest_ai_agent_result_capture_owner_release_approval_gate()
|
||||
except Exception as exc: # pragma: no cover - fail-closed read model guard
|
||||
return {
|
||||
"schema_version": "awooop_owner_release_package_bridge_v1",
|
||||
"status": "snapshot_unavailable",
|
||||
"source_schema_version": None,
|
||||
"source_task_id": None,
|
||||
"runtime_authority": "read_model_unavailable_no_write",
|
||||
"packet_count": 0,
|
||||
"approval_required_count": 0,
|
||||
"blocked_count": 0,
|
||||
"owner_release_approved_count": 0,
|
||||
"maintenance_window_approved_count": 0,
|
||||
"rollback_owner_confirmed_count": 0,
|
||||
"operator_action_count": 0,
|
||||
"packets": [],
|
||||
"operator_actions": [],
|
||||
"error": str(exc)[:160],
|
||||
}
|
||||
|
||||
rollups = payload.get("rollups") if isinstance(payload.get("rollups"), dict) else {}
|
||||
status = (
|
||||
payload.get("program_status")
|
||||
if isinstance(payload.get("program_status"), dict)
|
||||
else {}
|
||||
)
|
||||
return {
|
||||
"schema_version": "awooop_owner_release_package_bridge_v1",
|
||||
"status": "owner_review_required",
|
||||
"source_schema_version": payload.get("schema_version"),
|
||||
"source_task_id": status.get("current_task_id"),
|
||||
"runtime_authority": status.get("runtime_authority"),
|
||||
"packet_count": _safe_int(rollups.get("owner_release_approval_packet_count")),
|
||||
"approval_required_count": _safe_int(rollups.get("approval_required_packet_count")),
|
||||
"blocked_count": _safe_int(rollups.get("blocked_packet_count")),
|
||||
"owner_release_approved_count": _safe_int(rollups.get("owner_release_approved_count")),
|
||||
"maintenance_window_approved_count": _safe_int(rollups.get("maintenance_window_approved_count")),
|
||||
"rollback_owner_confirmed_count": _safe_int(rollups.get("rollback_owner_confirmed_count")),
|
||||
"operator_action_count": _safe_int(rollups.get("operator_action_count")),
|
||||
"packets": _compact_release_items(
|
||||
payload.get("owner_release_approval_packets"),
|
||||
id_field="packet_id",
|
||||
summary_field="approval_summary",
|
||||
),
|
||||
"operator_actions": _compact_release_items(
|
||||
payload.get("operator_actions"),
|
||||
id_field="action_id",
|
||||
summary_field="operator_instruction",
|
||||
limit=3,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _release_verifier_package_bridge() -> dict[str, Any]:
|
||||
try:
|
||||
payload = load_latest_ai_agent_result_capture_release_verifier_preflight_gate()
|
||||
except Exception as exc: # pragma: no cover - fail-closed read model guard
|
||||
return {
|
||||
"schema_version": "awooop_release_verifier_package_bridge_v1",
|
||||
"status": "snapshot_unavailable",
|
||||
"source_schema_version": None,
|
||||
"source_task_id": None,
|
||||
"runtime_authority": "read_model_unavailable_no_write",
|
||||
"verifier_count": 0,
|
||||
"rollback_count": 0,
|
||||
"maintenance_hold_count": 0,
|
||||
"live_apply_hold_count": 0,
|
||||
"owner_release_authorized_count": 0,
|
||||
"post_release_verifier_ready_count": 0,
|
||||
"live_apply_release_pass_count": 0,
|
||||
"operator_action_count": 0,
|
||||
"verifier_gates": [],
|
||||
"operator_actions": [],
|
||||
"error": str(exc)[:160],
|
||||
}
|
||||
|
||||
rollups = payload.get("rollups") if isinstance(payload.get("rollups"), dict) else {}
|
||||
status = (
|
||||
payload.get("program_status")
|
||||
if isinstance(payload.get("program_status"), dict)
|
||||
else {}
|
||||
)
|
||||
return {
|
||||
"schema_version": "awooop_release_verifier_package_bridge_v1",
|
||||
"status": "preflight_review_required",
|
||||
"source_schema_version": payload.get("schema_version"),
|
||||
"source_task_id": status.get("current_task_id"),
|
||||
"runtime_authority": status.get("runtime_authority"),
|
||||
"verifier_count": _safe_int(rollups.get("release_verifier_preflight_count")),
|
||||
"rollback_count": _safe_int(rollups.get("rollback_verifier_preflight_count")),
|
||||
"maintenance_hold_count": _safe_int(rollups.get("maintenance_window_verifier_hold_count")),
|
||||
"live_apply_hold_count": _safe_int(rollups.get("live_apply_verifier_hold_count")),
|
||||
"owner_release_authorized_count": _safe_int(rollups.get("owner_release_authorized_count")),
|
||||
"post_release_verifier_ready_count": _safe_int(rollups.get("post_release_verifier_ready_count")),
|
||||
"live_apply_release_pass_count": _safe_int(rollups.get("live_apply_release_pass_count")),
|
||||
"operator_action_count": _safe_int(rollups.get("operator_action_count")),
|
||||
"verifier_gates": _compact_release_items(
|
||||
payload.get("release_verifier_preflight_gates"),
|
||||
id_field="readback_id",
|
||||
summary_field="readback_summary",
|
||||
),
|
||||
"operator_actions": _compact_release_items(
|
||||
payload.get("operator_actions"),
|
||||
id_field="action_id",
|
||||
summary_field="operator_instruction",
|
||||
limit=3,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _apply_gate_closure_tasks(
|
||||
*,
|
||||
source_ref: str,
|
||||
safe_source_ref: str,
|
||||
catalog_id: str,
|
||||
owner_release_package: dict[str, Any],
|
||||
verifier_package: dict[str, Any],
|
||||
) -> list[dict[str, Any]]:
|
||||
return [
|
||||
{
|
||||
"key": "owner_release_packet_review",
|
||||
"status": "ready_for_owner_review",
|
||||
"owner_agent": "openclaw",
|
||||
"source_asset_id": "agent-result-capture-owner-release-approval-gate:P2-131",
|
||||
"work_item_id": f"owner-release-review:awoooi:{safe_source_ref}",
|
||||
"summary": (
|
||||
f"packets={_safe_int(owner_release_package.get('packet_count'))}; "
|
||||
f"approved={_safe_int(owner_release_package.get('owner_release_approved_count'))}"
|
||||
),
|
||||
"next_step": "review_owner_release_packet_and_evidence_refs",
|
||||
"runtime_write_allowed": False,
|
||||
},
|
||||
{
|
||||
"key": "maintenance_window_rollback_owner",
|
||||
"status": "approval_required",
|
||||
"owner_agent": "hermes",
|
||||
"source_asset_id": "agent-result-capture-owner-release-approval-gate:P2-131",
|
||||
"work_item_id": f"maintenance-rollback-review:awoooi:{safe_source_ref}",
|
||||
"summary": (
|
||||
f"maintenance_approved={_safe_int(owner_release_package.get('maintenance_window_approved_count'))}; "
|
||||
f"rollback_confirmed={_safe_int(owner_release_package.get('rollback_owner_confirmed_count'))}"
|
||||
),
|
||||
"next_step": "collect_maintenance_window_and_rollback_owner",
|
||||
"runtime_write_allowed": False,
|
||||
},
|
||||
{
|
||||
"key": "controlled_execution_authorization",
|
||||
"status": "blocked_before_runtime_gate",
|
||||
"owner_agent": "sre",
|
||||
"source_asset_id": f"ansible-apply-candidate:{catalog_id}",
|
||||
"work_item_id": f"controlled-execution-gate:awoooi:{safe_source_ref}",
|
||||
"summary": f"incident={source_ref}; runtime_gate=0",
|
||||
"next_step": "owner_release_required_before_controlled_apply",
|
||||
"runtime_write_allowed": False,
|
||||
},
|
||||
{
|
||||
"key": "post_apply_verifier_preflight",
|
||||
"status": "preflight_review_required",
|
||||
"owner_agent": "openclaw",
|
||||
"source_asset_id": "agent-result-capture-release-verifier-preflight-gate:P2-136",
|
||||
"work_item_id": f"post-apply-verifier:awoooi:{safe_source_ref}",
|
||||
"summary": (
|
||||
f"verifier={_safe_int(verifier_package.get('verifier_count'))}; "
|
||||
f"ready={_safe_int(verifier_package.get('post_release_verifier_ready_count'))}"
|
||||
),
|
||||
"next_step": "review_post_apply_verifier_before_any_apply",
|
||||
"runtime_write_allowed": False,
|
||||
},
|
||||
{
|
||||
"key": "km_playbook_trust_writeback_plan",
|
||||
"status": "blocked_until_verifier_passes",
|
||||
"owner_agent": "hermes",
|
||||
"source_asset_id": f"playbook-trust-update-candidate:{catalog_id}",
|
||||
"work_item_id": f"km-playbook-writeback:awoooi:{safe_source_ref}",
|
||||
"summary": "km_write=0; playbook_trust_write=0",
|
||||
"next_step": "prepare_km_and_playbook_writeback_after_verified_execution",
|
||||
"runtime_write_allowed": False,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def _status_chain_ansible_apply_gate_handoff(
|
||||
*,
|
||||
ansible_dry_run_only: bool,
|
||||
@@ -4180,6 +4397,15 @@ def _status_chain_ansible_apply_gate_handoff(
|
||||
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))
|
||||
owner_release_package = _owner_release_package_bridge()
|
||||
verifier_package = _release_verifier_package_bridge()
|
||||
closure_tasks = _apply_gate_closure_tasks(
|
||||
source_ref=str(source_ref),
|
||||
safe_source_ref=safe_source_ref,
|
||||
catalog_id=str(catalog_id),
|
||||
owner_release_package=owner_release_package,
|
||||
verifier_package=verifier_package,
|
||||
)
|
||||
|
||||
return {
|
||||
"schema_version": "awooop_automation_handoff_v1",
|
||||
@@ -4244,6 +4470,9 @@ def _status_chain_ansible_apply_gate_handoff(
|
||||
"status": "read_only",
|
||||
},
|
||||
],
|
||||
"owner_release_package": owner_release_package,
|
||||
"release_verifier_package": verifier_package,
|
||||
"closure_tasks": closure_tasks,
|
||||
},
|
||||
"candidate": {
|
||||
"catalog_id": catalog_id,
|
||||
|
||||
Reference in New Issue
Block a user