feat(awooop): surface ai automation node receipts
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / tests (push) Has been cancelled

This commit is contained in:
Your Name
2026-07-02 18:35:24 +08:00
parent 5b5ef7fe2d
commit bff4cf5388
5 changed files with 548 additions and 0 deletions

View File

@@ -47,6 +47,20 @@ _METRIC_LINE_RE = re.compile(
_COMMANDER_INSERTED_REQUIREMENT_SOURCE = (
"docs/workplans/2026-07-02-commander-inserted-requirements-priority-ledger.md"
)
_AI_AUTOMATION_NODE_RECEIPT_SCHEMA_VERSION = "ai_automation_node_receipt_v1"
_AI_AUTOMATION_NODE_RECEIPT_REQUIRED_FIELDS = [
"trace_id",
"run_id",
"work_item_id",
"node_id",
"node_status",
"timestamp",
"evidence_refs",
"verifier_result",
"rollback_result",
"km_writeback_ref",
"playbook_trust_writeback_ref",
]
_COMMANDER_INSERTED_REQUIREMENT_WORK_ITEMS: list[dict[str, Any]] = [
{
"id": "CIR-P0-001",
@@ -816,6 +830,7 @@ def load_latest_awoooi_priority_work_order_readback(
_require_mainline_consistency(payload, str(path))
_apply_commander_inserted_requirement_work_items(payload)
_mark_runtime_generated_at(payload)
apply_ai_automation_node_receipts(payload)
return payload
@@ -965,6 +980,7 @@ def apply_controlled_cd_lane_live_metric_readback(
)
_mark_runtime_generated_at(payload)
apply_ai_automation_node_receipts(payload)
def apply_stockplatform_public_api_runtime_readback(
@@ -1516,6 +1532,7 @@ def apply_ai_loop_current_blocker_execution_queue(
pressure_blocker=pressure_blocker,
node_load_classifier=node_load_classifier,
)
apply_ai_automation_node_receipts(payload)
return
if not _ai_loop_current_blocker_can_override(
@@ -2101,6 +2118,7 @@ def apply_ai_loop_current_blocker_execution_queue(
summary["ai_loop_current_blocker_forbidden_runtime_action_count"] = len(
forbidden_runtime_actions
)
apply_ai_automation_node_receipts(payload)
def _record_ai_loop_current_blocker_production_resolution(
@@ -2226,6 +2244,7 @@ def _record_ai_loop_current_blocker_production_resolution(
if blocker and blocker not in resolved_blockers
]
break
apply_ai_automation_node_receipts(payload)
def _ai_loop_current_blocker_can_override(
@@ -3371,6 +3390,213 @@ def _apply_commander_inserted_requirement_work_items(
)
def apply_ai_automation_node_receipts(payload: dict[str, Any]) -> None:
"""Refresh metadata-only AI automation node receipts after live overlays."""
_apply_ai_automation_node_receipts(payload)
def _apply_ai_automation_node_receipts(payload: dict[str, Any]) -> None:
summary = _dict(payload.setdefault("summary", {}))
rollups = _dict(payload.setdefault("rollups", {}))
runtime_timestamp = str(
payload.get("runtime_readback_generated_at")
or summary.get("runtime_readback_generated_at")
or payload.get("generated_at")
or ""
)
source_sha = str(summary.get("latest_successful_deployed_source_short_sha") or "")
cd_run_id = str(summary.get("ai_loop_current_blocker_current_cd_run_id") or "")
cd_run_status = str(
summary.get("ai_loop_current_blocker_current_cd_run_status") or ""
)
blocker_id = str(summary.get("ai_loop_current_blocker_id") or "")
safe_next_action_id = str(
summary.get("ai_loop_current_blocker_safe_next_action_id") or ""
)
safe_next_action_stage = str(
summary.get("ai_loop_current_blocker_safe_next_action_stage") or ""
)
receipt_inputs = _strings(
summary.get("ai_loop_current_blocker_harbor_recovery_receipt_input_ids")
)
receipt_outputs = _strings(
summary.get("ai_loop_current_blocker_harbor_recovery_receipt_output_ids")
)
queue_fields = _strings(
summary.get("ai_loop_current_blocker_queue_readback_normalizer_field_ids")
)
log_grouping_keys = _strings(summary.get("ai_loop_log_source_grouping_keys"))
base_refs = [
"awoooi-priority-work-order-readback",
_COMMANDER_INSERTED_REQUIREMENT_SOURCE,
]
if source_sha:
base_refs.append(f"production_source:{source_sha}")
if cd_run_id:
base_refs.append(f"gitea_cd_run:{cd_run_id}:{cd_run_status or 'unknown'}")
node_specs = [
{
"node_id": "sensor_evidence",
"node_label": "Sensor / Evidence",
"node_status": "ready",
"work_item_id": "CIR-P0-AILOOP-001",
"lane_id": "p0_runtime_lane",
"evidence_refs": [*base_refs, *receipt_inputs[:3]],
"verifier_result": "production_readback_present",
"next_action": "keep source/CD/runtime readback attached to this trace",
},
{
"node_id": "normalizer_log_tags",
"node_label": "Normalizer / LOG tags",
"node_status": "ready" if queue_fields or log_grouping_keys else "queued",
"work_item_id": "CIR-P0-LOG-002",
"lane_id": "log_tagging_classification_clustering",
"evidence_refs": [*queue_fields[:4], *log_grouping_keys[:4]],
"verifier_result": "queue_normalizer_fields_readback"
if queue_fields
else "normalizer_contract_required",
"next_action": "extend tag taxonomy to Telegram, CPU, backup, freshness",
},
{
"node_id": "ai_lane_route",
"node_label": "AI Lane",
"node_status": "ready",
"work_item_id": "CIR-P0-AILOOP-001",
"lane_id": "ai_loop_agent_mainline",
"evidence_refs": [blocker_id, safe_next_action_stage],
"verifier_result": "ai_loop_current_blocker_routed",
"next_action": "keep every alert/work item attached to an AI lane",
},
{
"node_id": "candidate_action",
"node_label": "Candidate",
"node_status": "ready" if safe_next_action_id else "queued",
"work_item_id": "CIR-P0-AILOOP-002",
"lane_id": "p0_runtime_lane",
"evidence_refs": [safe_next_action_id, safe_next_action_stage],
"verifier_result": "safe_next_action_readback"
if safe_next_action_id
else "candidate_action_required",
"next_action": "emit candidate action with target selector and dry-run",
},
{
"node_id": "gate_policy",
"node_label": "Gate",
"node_status": "ready",
"work_item_id": "CIR-P0-013",
"lane_id": "controlled_apply_gate_taxonomy",
"evidence_refs": ["non_accident_gate_as_evidence", "break_glass_reserved"],
"verifier_result": "controlled_apply_policy_readback",
"next_action": "keep low/medium/high in controlled apply unless hard blocker",
},
{
"node_id": "execution_boundary",
"node_label": "Execution Boundary",
"node_status": "queued",
"work_item_id": "CIR-P0-AILOOP-002",
"lane_id": "telegram_alert_ai_automation",
"evidence_refs": ["metadata_only", "no_secret_no_runtime_write"],
"verifier_result": "execution_receipt_required",
"next_action": "attach Telegram alert receipt and controlled executor result",
},
{
"node_id": "post_verifier",
"node_label": "Verifier",
"node_status": "ready" if receipt_outputs else "queued",
"work_item_id": "CIR-P0-AILOOP-002",
"lane_id": "p0_runtime_lane",
"evidence_refs": receipt_outputs[:4],
"verifier_result": "post_verifier_receipt_readback"
if receipt_outputs
else "post_verifier_required",
"next_action": "read back route/API/UI/verifier output before closing",
},
{
"node_id": "learning_writeback",
"node_label": "Learning / Writeback",
"node_status": "queued",
"work_item_id": "CIR-P1-KM-002",
"lane_id": "km_rag_mcp_playbook_integration",
"evidence_refs": ["KM", "RAG", "MCP", "PlayBook trust"],
"verifier_result": "writeback_receipt_required",
"next_action": "write KM/RAG/MCP/PlayBook trust refs after verifier",
},
]
receipts = []
for index, node in enumerate(node_specs, start=1):
receipts.append(
{
"schema_version": _AI_AUTOMATION_NODE_RECEIPT_SCHEMA_VERSION,
"trace_id": "trace:awoooi-ai-loop-current-p0",
"run_id": cd_run_id or f"priority-readback:{source_sha or 'runtime'}",
"node_order": index,
"timestamp": runtime_timestamp,
"metadata_only": True,
"rollback_result": "not_started_no_runtime_write",
"km_writeback_ref": ""
if node["node_status"] != "queued"
else "queued",
"playbook_trust_writeback_ref": ""
if node["node_status"] != "queued"
else "queued",
"mcp_evidence_ref": "metadata_registry",
"telegram_receipt_ref": "metadata_only"
if node["lane_id"] == "telegram_alert_ai_automation"
else "",
**node,
}
)
status_counts = {
status: sum(1 for item in receipts if item["node_status"] == status)
for status in ("ready", "queued", "blocked")
}
lanes = sorted({str(item["lane_id"]) for item in receipts})
work_items = sorted({str(item["work_item_id"]) for item in receipts})
payload["ai_automation_node_receipt_schema"] = {
"schema_version": _AI_AUTOMATION_NODE_RECEIPT_SCHEMA_VERSION,
"required_fields": _AI_AUTOMATION_NODE_RECEIPT_REQUIRED_FIELDS,
"metadata_only": True,
"hard_blockers_preserved": [
"secret_plaintext",
"destructive_data_change",
"reboot_or_node_drain",
"force_push_or_repo_ref_delete",
"paid_provider_route_change",
],
}
payload["ai_automation_node_receipts"] = receipts
rollups["ai_automation_node_receipt_count"] = len(receipts)
rollups["ai_automation_node_receipt_ready_count"] = status_counts["ready"]
rollups["ai_automation_node_receipt_queued_count"] = status_counts["queued"]
rollups["ai_automation_node_receipt_blocked_count"] = status_counts["blocked"]
rollups["ai_automation_node_receipt_required_field_count"] = len(
_AI_AUTOMATION_NODE_RECEIPT_REQUIRED_FIELDS
)
rollups["ai_automation_node_receipt_metadata_only"] = True
rollups["ai_automation_node_receipt_lanes"] = lanes
rollups["ai_automation_node_receipt_work_items"] = work_items
summary["ai_automation_node_receipt_schema_version"] = (
_AI_AUTOMATION_NODE_RECEIPT_SCHEMA_VERSION
)
summary["ai_automation_node_receipt_count"] = len(receipts)
summary["ai_automation_node_receipt_ready_count"] = status_counts["ready"]
summary["ai_automation_node_receipt_queued_count"] = status_counts["queued"]
summary["ai_automation_node_receipt_blocked_count"] = status_counts["blocked"]
summary["ai_automation_node_receipt_required_field_count"] = len(
_AI_AUTOMATION_NODE_RECEIPT_REQUIRED_FIELDS
)
summary["ai_automation_node_receipt_metadata_only"] = True
summary["ai_automation_node_receipt_lanes"] = lanes
summary["ai_automation_node_receipt_work_items"] = work_items
def _mark_runtime_generated_at(payload: dict[str, Any]) -> None:
snapshot_generated_at = str(
payload.get("snapshot_generated_at") or payload.get("generated_at") or ""