feat(awooop): surface owner release closure tasks
All checks were successful
Code Review / ai-code-review (push) Successful in 13s
CD Pipeline / tests (push) Successful in 1m42s
CD Pipeline / build-and-deploy (push) Successful in 5m17s
CD Pipeline / post-deploy-checks (push) Successful in 2m11s

This commit is contained in:
Your Name
2026-06-26 07:16:15 +08:00
parent 1fd5e2a8b0
commit c67dc92f19
5 changed files with 538 additions and 4 deletions

View File

@@ -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,