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

This commit is contained in:
Your Name
2026-06-29 18:11:37 +08:00
parent 5abc1cc438
commit 00212d2afe
5 changed files with 309 additions and 8 deletions

View File

@@ -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 下受控自動處理。"

View File

@@ -38,7 +38,7 @@ def test_ai_agent_autonomous_runtime_control_uses_current_owner_directive():
"cd_internal_control_plane_readback_retry_20260628_2"
)
assert data["program_status"]["legacy_no_send_no_live_rules_overridden"] is True
assert data["program_status"]["implementation_completion_percent"] == 95
assert data["program_status"]["implementation_completion_percent"] == 100
assert data["current_policy"]["low_risk_controlled_apply_allowed"] is True
assert data["current_policy"]["medium_risk_controlled_apply_allowed"] is True
assert data["current_policy"]["high_risk_controlled_apply_allowed"] is True
@@ -442,6 +442,15 @@ def test_runtime_receipt_readback_summarizes_live_executor_closure_rows():
assert taxonomy["rollups"]["source_family_count"] == 10
assert taxonomy["rollups"]["active_source_family_count"] == 10
assert taxonomy["rollups"]["classified_event_total"] > 0
assert {
"project",
"product",
"website",
"service",
"package",
"tool",
"source_family",
}.issubset(set(taxonomy["required_label_dimensions"]))
assert taxonomy["public_safety"]["raw_secret_collection_allowed"] is False
assert taxonomy["public_safety"]["unredacted_payload_storage_allowed"] is False
decision_wiring = readback["agent_decision_wiring"]
@@ -520,6 +529,25 @@ def test_runtime_receipt_readback_summarizes_live_executor_closure_rows():
assert ui_productization["public_safety"]["manual_default_outcome_allowed"] is False
assert ui_productization["rollups"]["required_surface_present_count"] == 5
assert ui_productization["rollups"]["segmented_filter_count"] == 5
multi_product = readback["multi_product_taxonomy"]
assert multi_product["schema_version"] == "ai_agent_multi_product_taxonomy_contract_v1"
assert multi_product["status"] == "completed"
assert multi_product["missing_product_scope_ids"] == []
assert multi_product["missing_required_dimension_ids"] == []
assert {
"awoooi",
"stockplatform",
"vibework",
"momo",
"awooogo",
"tsenyang",
"agent_bounty_protocol",
"public_websites",
} == {scope["product_id"] for scope in multi_product["product_scopes"]}
assert multi_product["rollups"]["product_scope_count"] == 8
assert multi_product["rollups"]["contract_ready_product_scope_count"] == 8
assert multi_product["rollups"]["runtime_adapter_active_count"] == 1
assert multi_product["public_safety"]["external_product_runtime_write_enabled_on_read"] is False
progress = readback["work_item_progress"]
assert progress["schema_version"] == "ai_agent_automation_work_item_progress_v1"
ordered_ids = [item["work_item_id"] for item in progress["ordered_items"]]
@@ -545,12 +573,13 @@ def test_runtime_receipt_readback_summarizes_live_executor_closure_rows():
assert progress["ordered_items"][8]["remaining_alert_noise_stage_count"] == 0
assert progress["ordered_items"][9]["status"] == "completed"
assert progress["ordered_items"][9]["remaining_ui_surface_count"] == 0
assert progress["ordered_items"][10]["status"] == "pending"
assert progress["ordered_items"][10]["status"] == "completed"
assert progress["ordered_items"][10]["remaining_product_scope_count"] == 0
assert progress["source_family_items"]
assert {item["status"] for item in progress["source_family_items"]} == {"completed"}
assert progress["rollups"]["source_family_work_item_count"] == 10
assert progress["rollups"]["completed_count"] == 20
assert progress["rollups"]["pending_count"] == 1
assert progress["rollups"]["completed_count"] == 21
assert progress["rollups"]["pending_count"] == 0
def test_runtime_receipt_readback_classifies_closed_failed_apply_as_ai_repair():

View File

@@ -11361,10 +11361,12 @@
"traceCaption": "{count} stages / {missing} missing",
"taxonomy": {
"sources": "Log sources",
"products": "Product scopes",
"labels": "Label dimensions",
"events": "Classified events",
"learning": "Learning sources",
"workItems": "Work items",
"productsDetail": "adapter active {active} / missing dimensions {missing}",
"workItemsDetail": "Active {active} / pending {pending} / blocked {blocked}"
},
"policy": {

View File

@@ -11361,10 +11361,12 @@
"traceCaption": "{count} 節點 / 缺 {missing}",
"taxonomy": {
"sources": "Log 來源",
"products": "產品範圍",
"labels": "貼標維度",
"events": "分類事件",
"learning": "學習來源",
"workItems": "工作項目",
"productsDetail": "adapter active {active} / 缺維度 {missing}",
"workItemsDetail": "進行 {active} / 待辦 {pending} / 阻塞 {blocked}"
},
"policy": {

View File

@@ -93,6 +93,16 @@ type RuntimeReceiptReadback = {
learning_source_family_count?: number | null;
} | null;
} | null;
multi_product_taxonomy?: {
status?: string | null;
missing_product_scope_ids?: string[] | null;
rollups?: {
product_scope_count?: number | null;
contract_ready_product_scope_count?: number | null;
runtime_adapter_active_count?: number | null;
missing_required_dimension_count?: number | null;
} | null;
} | null;
agent_decision_wiring?: {
status?: string | null;
missing_required_stage_ids?: string[] | null;
@@ -285,6 +295,7 @@ export function AutonomousRuntimeReceiptPanel({
const traceLedger = readback?.trace_ledger;
const logTaxonomy = readback?.log_integration_taxonomy;
const logRollups = logTaxonomy?.rollups ?? {};
const multiProductRollups = readback?.multi_product_taxonomy?.rollups ?? {};
const decisionRollups = readback?.agent_decision_wiring?.rollups ?? {};
const decisionMissing = readback?.agent_decision_wiring?.missing_required_stage_ids ?? [];
const learningRollups = readback?.learning_loop?.rollups ?? {};
@@ -605,7 +616,7 @@ export function AutonomousRuntimeReceiptPanel({
})}
</div>
<div className="grid gap-px border-t border-[#e0ddd4] bg-[#e0ddd4] md:grid-cols-5">
<div className="grid gap-px border-t border-[#e0ddd4] bg-[#e0ddd4] md:grid-cols-2 xl:grid-cols-6">
<div className="bg-white px-4 py-3">
<p className="text-xs font-semibold text-[#77736a]">{t("taxonomy.sources")}</p>
<p className="mt-1 text-sm font-semibold text-[#141413]">
@@ -614,6 +625,32 @@ export function AutonomousRuntimeReceiptPanel({
{numberValue(rollups.live_log_source_family_count ?? logRollups.source_family_count)}
</p>
</div>
<div className="bg-white px-4 py-3">
<p className="text-xs font-semibold text-[#77736a]">{t("taxonomy.products")}</p>
<p className="mt-1 text-sm font-semibold text-[#141413]">
{numberValue(
rollups.live_multi_product_taxonomy_contract_ready_count
?? multiProductRollups.contract_ready_product_scope_count
)}
{" / "}
{numberValue(
rollups.live_multi_product_taxonomy_product_scope_count
?? multiProductRollups.product_scope_count
)}
</p>
<p className="mt-1 text-xs leading-5 text-[#5f5b52]">
{t("taxonomy.productsDetail", {
active: numberValue(
rollups.live_multi_product_taxonomy_runtime_adapter_active_count
?? multiProductRollups.runtime_adapter_active_count
),
missing: numberValue(
rollups.live_multi_product_taxonomy_missing_dimension_count
?? multiProductRollups.missing_required_dimension_count
),
})}
</p>
</div>
<div className="bg-white px-4 py-3">
<p className="text-xs font-semibold text-[#77736a]">{t("taxonomy.labels")}</p>
<p className="mt-1 text-sm font-semibold text-[#141413]">