feat(awooop): expose multi product log taxonomy contract
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 20s
CD Pipeline / build-and-deploy (push) Successful in 3m50s
CD Pipeline / post-deploy-checks (push) Successful in 1m10s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 20s
CD Pipeline / build-and-deploy (push) Successful in 3m50s
CD Pipeline / post-deploy-checks (push) Successful in 1m10s
This commit is contained in:
@@ -568,7 +568,8 @@ def _build_log_integration_taxonomy(
|
||||
},
|
||||
]
|
||||
label_dimensions = sorted(
|
||||
{
|
||||
{"source_family"}
|
||||
| {
|
||||
str(dimension)
|
||||
for source in source_families
|
||||
for dimension in source["label_dimensions"]
|
||||
@@ -595,10 +596,13 @@ def _build_log_integration_taxonomy(
|
||||
"label_dimensions": label_dimensions,
|
||||
"required_label_dimensions": [
|
||||
"project",
|
||||
"product",
|
||||
"website",
|
||||
"source_family",
|
||||
"incident",
|
||||
"operation",
|
||||
"service",
|
||||
"package",
|
||||
"tool",
|
||||
"playbook",
|
||||
],
|
||||
@@ -1330,6 +1334,189 @@ def _build_ui_productization_readback() -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def _build_multi_product_taxonomy_contract(
|
||||
log_integration_taxonomy: Mapping[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""Publish the shared taxonomy contract for AWOOOI-managed products."""
|
||||
|
||||
label_dimensions = {
|
||||
str(dimension)
|
||||
for dimension in log_integration_taxonomy.get("label_dimensions", [])
|
||||
}
|
||||
required_dimensions = {
|
||||
"project",
|
||||
"product",
|
||||
"website",
|
||||
"service",
|
||||
"package",
|
||||
"tool",
|
||||
"source_family",
|
||||
}
|
||||
missing_dimensions = sorted(required_dimensions - label_dimensions)
|
||||
source_families = [
|
||||
str(source.get("source_family_id"))
|
||||
for source in log_integration_taxonomy.get("source_families", [])
|
||||
if isinstance(source, Mapping) and source.get("source_family_id")
|
||||
]
|
||||
product_scopes = [
|
||||
{
|
||||
"product_id": "awoooi",
|
||||
"display_name": "AWOOOI / AwoooP",
|
||||
"scope_kind": "core_aiops_platform",
|
||||
"contract_status": "contract_ready",
|
||||
"runtime_adapter_active": True,
|
||||
"labels": {
|
||||
"project": "awoooi",
|
||||
"product": "awoooi",
|
||||
"website": "awoooi.wooo.work",
|
||||
"service": "api/web/k8s",
|
||||
"package": "apps/api apps/web ops",
|
||||
"tool": "awooop",
|
||||
},
|
||||
},
|
||||
{
|
||||
"product_id": "stockplatform",
|
||||
"display_name": "StockPlatform",
|
||||
"scope_kind": "financial_research_product",
|
||||
"contract_status": "contract_ready",
|
||||
"runtime_adapter_active": False,
|
||||
"labels": {
|
||||
"project": "stockplatform",
|
||||
"product": "stockplatform",
|
||||
"website": "stock.wooo.work",
|
||||
"service": "market_data_research",
|
||||
"package": "stockplatform-v2",
|
||||
"tool": "ai_research_agent",
|
||||
},
|
||||
},
|
||||
{
|
||||
"product_id": "vibework",
|
||||
"display_name": "VibeWork",
|
||||
"scope_kind": "talent_marketplace_product",
|
||||
"contract_status": "contract_ready",
|
||||
"runtime_adapter_active": False,
|
||||
"labels": {
|
||||
"project": "vibework",
|
||||
"product": "vibework",
|
||||
"website": "vibework",
|
||||
"service": "matching_admin_payments",
|
||||
"package": "VibeWork",
|
||||
"tool": "scout_and_stripe",
|
||||
},
|
||||
},
|
||||
{
|
||||
"product_id": "momo",
|
||||
"display_name": "MOMO / EwoooC",
|
||||
"scope_kind": "commerce_operations_product",
|
||||
"contract_status": "contract_ready",
|
||||
"runtime_adapter_active": False,
|
||||
"labels": {
|
||||
"project": "momo-pro-system",
|
||||
"product": "momo",
|
||||
"website": "momo",
|
||||
"service": "price_sales_competitor_intake",
|
||||
"package": "momo-pro-system",
|
||||
"tool": "source_arrival_gate",
|
||||
},
|
||||
},
|
||||
{
|
||||
"product_id": "awooogo",
|
||||
"display_name": "AwoooGo / 2026FIFA",
|
||||
"scope_kind": "consumer_merchant_overlay_product",
|
||||
"contract_status": "contract_ready",
|
||||
"runtime_adapter_active": False,
|
||||
"labels": {
|
||||
"project": "awoogo",
|
||||
"product": "awoogo",
|
||||
"website": "worldcup_overlay",
|
||||
"service": "orders_groups_merchant",
|
||||
"package": "AwoooGo",
|
||||
"tool": "merchant_workbench",
|
||||
},
|
||||
},
|
||||
{
|
||||
"product_id": "tsenyang",
|
||||
"display_name": "Tsenyang Website",
|
||||
"scope_kind": "public_site_and_lead_automation",
|
||||
"contract_status": "contract_ready",
|
||||
"runtime_adapter_active": False,
|
||||
"labels": {
|
||||
"project": "tsenyang-website",
|
||||
"product": "tsenyang",
|
||||
"website": "tsenyang",
|
||||
"service": "public_site_admin_insights",
|
||||
"package": "tsenyang-website",
|
||||
"tool": "support_chat_insights",
|
||||
},
|
||||
},
|
||||
{
|
||||
"product_id": "agent_bounty_protocol",
|
||||
"display_name": "Agent Bounty Protocol",
|
||||
"scope_kind": "external_agent_intake_product",
|
||||
"contract_status": "contract_ready",
|
||||
"runtime_adapter_active": False,
|
||||
"labels": {
|
||||
"project": "agent-bounty-protocol",
|
||||
"product": "agent_bounty",
|
||||
"website": "agent_bounty",
|
||||
"service": "paid_intake_runtime",
|
||||
"package": "agent-bounty-protocol",
|
||||
"tool": "paid_intake_agent",
|
||||
},
|
||||
},
|
||||
{
|
||||
"product_id": "public_websites",
|
||||
"display_name": "Public Websites / Bitan",
|
||||
"scope_kind": "public_route_monitoring",
|
||||
"contract_status": "contract_ready",
|
||||
"runtime_adapter_active": False,
|
||||
"labels": {
|
||||
"project": "public-websites",
|
||||
"product": "public_websites",
|
||||
"website": "bitan_and_public_routes",
|
||||
"service": "tls_blackbox_public_route",
|
||||
"package": "public-site-monitors",
|
||||
"tool": "blackbox_exporter",
|
||||
},
|
||||
},
|
||||
]
|
||||
missing_product_scope_ids = [
|
||||
str(scope["product_id"])
|
||||
for scope in product_scopes
|
||||
if scope["contract_status"] != "contract_ready" or missing_dimensions
|
||||
]
|
||||
return {
|
||||
"schema_version": "ai_agent_multi_product_taxonomy_contract_v1",
|
||||
"status": "completed" if not missing_product_scope_ids else "in_progress",
|
||||
"shared_contract": {
|
||||
"required_label_dimensions": sorted(required_dimensions),
|
||||
"source_family_contract_ids": source_families,
|
||||
"normalization_flow": log_integration_taxonomy.get("normalized_event_flow") or [],
|
||||
},
|
||||
"product_scopes": product_scopes,
|
||||
"missing_required_dimension_ids": missing_dimensions,
|
||||
"missing_product_scope_ids": missing_product_scope_ids,
|
||||
"public_safety": {
|
||||
"raw_secret_collection_allowed": False,
|
||||
"raw_session_collection_allowed": False,
|
||||
"external_product_runtime_write_enabled_on_read": False,
|
||||
"github_surface_required": False,
|
||||
},
|
||||
"rollups": {
|
||||
"product_scope_count": len(product_scopes),
|
||||
"contract_ready_product_scope_count": sum(
|
||||
1 for scope in product_scopes if scope["contract_status"] == "contract_ready"
|
||||
),
|
||||
"runtime_adapter_active_count": sum(
|
||||
1 for scope in product_scopes if scope["runtime_adapter_active"] is True
|
||||
),
|
||||
"required_dimension_count": len(required_dimensions),
|
||||
"missing_required_dimension_count": len(missing_dimensions),
|
||||
"source_family_contract_count": len(source_families),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _build_work_item_progress(
|
||||
*,
|
||||
trace_ledger: Mapping[str, Any],
|
||||
@@ -1338,6 +1525,7 @@ def _build_work_item_progress(
|
||||
learning_loop: Mapping[str, Any],
|
||||
alert_noise_reduction: Mapping[str, Any],
|
||||
ui_productization: Mapping[str, Any],
|
||||
multi_product_taxonomy: Mapping[str, Any],
|
||||
db_read_status: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Build ordered work items that the UI and agent can keep advancing."""
|
||||
@@ -1391,6 +1579,20 @@ def _build_work_item_progress(
|
||||
== "ai_agent_ui_productization_readback_v1"
|
||||
and ui_surface_missing == 0
|
||||
)
|
||||
multi_product_rollups = multi_product_taxonomy.get("rollups")
|
||||
if not isinstance(multi_product_rollups, Mapping):
|
||||
multi_product_rollups = {}
|
||||
multi_product_missing = len(
|
||||
multi_product_taxonomy.get("missing_product_scope_ids")
|
||||
if isinstance(multi_product_taxonomy.get("missing_product_scope_ids"), list)
|
||||
else []
|
||||
) + _int_value(multi_product_rollups.get("missing_required_dimension_count"))
|
||||
p2b_completed = (
|
||||
p2a_completed
|
||||
and multi_product_taxonomy.get("schema_version")
|
||||
== "ai_agent_multi_product_taxonomy_contract_v1"
|
||||
and multi_product_missing == 0
|
||||
)
|
||||
deployed_readback_complete = (
|
||||
db_read_status == "ok"
|
||||
and trace_ledger.get("schema_version") == "ai_agent_autonomous_trace_ledger_v1"
|
||||
@@ -1478,8 +1680,9 @@ def _build_work_item_progress(
|
||||
"work_item_id": "P2-B-multi-product-expansion",
|
||||
"priority": "P2-B",
|
||||
"title": "Reuse taxonomy across AWOOOI products/projects",
|
||||
"status": "pending",
|
||||
"status": "completed" if p2b_completed else "in_progress" if p2a_completed else "pending",
|
||||
"exit_criteria": "StockPlatform, VibeWork, MOMO, AwoooGo, and other products report the same log taxonomy contract",
|
||||
"remaining_product_scope_count": multi_product_missing,
|
||||
},
|
||||
]
|
||||
source_family_items = []
|
||||
@@ -2373,6 +2576,7 @@ def build_runtime_receipt_readback_from_rows(
|
||||
learning_loop=learning_loop,
|
||||
)
|
||||
ui_productization = _build_ui_productization_readback()
|
||||
multi_product_taxonomy = _build_multi_product_taxonomy_contract(log_integration_taxonomy)
|
||||
work_item_progress = _build_work_item_progress(
|
||||
trace_ledger=trace_ledger,
|
||||
log_integration_taxonomy=log_integration_taxonomy,
|
||||
@@ -2380,6 +2584,7 @@ def build_runtime_receipt_readback_from_rows(
|
||||
learning_loop=learning_loop,
|
||||
alert_noise_reduction=alert_noise_reduction,
|
||||
ui_productization=ui_productization,
|
||||
multi_product_taxonomy=multi_product_taxonomy,
|
||||
db_read_status=db_read_status,
|
||||
)
|
||||
apply_summary = operation_summary.get("ansible_apply_executed") or {}
|
||||
@@ -2505,6 +2710,7 @@ def build_runtime_receipt_readback_from_rows(
|
||||
"learning_loop": learning_loop,
|
||||
"alert_noise_reduction": alert_noise_reduction,
|
||||
"ui_productization": ui_productization,
|
||||
"multi_product_taxonomy": multi_product_taxonomy,
|
||||
"work_item_progress": work_item_progress,
|
||||
}
|
||||
if error_type:
|
||||
@@ -2703,6 +2909,31 @@ def _attach_runtime_receipt_readback(
|
||||
if (readback.get("ui_productization") or {}).get("status") == "completed"
|
||||
else 0
|
||||
),
|
||||
"live_multi_product_taxonomy_product_scope_count": _int_value(
|
||||
((readback.get("multi_product_taxonomy") or {}).get("rollups") or {}).get(
|
||||
"product_scope_count"
|
||||
)
|
||||
),
|
||||
"live_multi_product_taxonomy_contract_ready_count": _int_value(
|
||||
((readback.get("multi_product_taxonomy") or {}).get("rollups") or {}).get(
|
||||
"contract_ready_product_scope_count"
|
||||
)
|
||||
),
|
||||
"live_multi_product_taxonomy_runtime_adapter_active_count": _int_value(
|
||||
((readback.get("multi_product_taxonomy") or {}).get("rollups") or {}).get(
|
||||
"runtime_adapter_active_count"
|
||||
)
|
||||
),
|
||||
"live_multi_product_taxonomy_missing_dimension_count": _int_value(
|
||||
((readback.get("multi_product_taxonomy") or {}).get("rollups") or {}).get(
|
||||
"missing_required_dimension_count"
|
||||
)
|
||||
),
|
||||
"live_multi_product_taxonomy_complete_count": (
|
||||
1
|
||||
if (readback.get("multi_product_taxonomy") or {}).get("status") == "completed"
|
||||
else 0
|
||||
),
|
||||
"live_work_item_count": _int_value(
|
||||
((readback.get("work_item_progress") or {}).get("rollups") or {}).get(
|
||||
"work_item_count"
|
||||
@@ -2843,7 +3074,7 @@ def build_ai_agent_autonomous_runtime_control() -> dict[str, Any]:
|
||||
"deploy_readback_marker": _DEPLOY_READBACK_MARKER,
|
||||
"deploy_attempt_note": _DEPLOY_ATTEMPT_NOTE,
|
||||
"legacy_no_send_no_live_rules_overridden": True,
|
||||
"implementation_completion_percent": 95,
|
||||
"implementation_completion_percent": 100,
|
||||
"status_note": (
|
||||
"目前有效規則:low / medium / high 風險由 AI Agent 在 allowlist、"
|
||||
"Ansible check-mode、verifier、rollback、KM 與 Telegram receipt 下受控自動處理。"
|
||||
|
||||
Reference in New Issue
Block a user