Files
awoooi/scripts/dev/ai-agent-market-radar-readback.py
Your Name 00d5000fd6
Some checks failed
Code Review / ai-code-review (push) Successful in 13s
CD Pipeline / tests (push) Successful in 1m49s
CD Pipeline / build-and-deploy (push) Successful in 7m11s
CD Pipeline / post-deploy-checks (push) Failing after 1m24s
Ansible / Reboot Recovery Contract / validate (push) Has been cancelled
fix(governance): 澄清 AI Agent 市場雷達證據基準
2026-06-25 10:53:43 +08:00

439 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Build the AWOOOI AI Agent market radar readback artifact."""
from __future__ import annotations
import argparse
import json
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
def build_radar(
*,
market_watch: dict[str, Any],
governance_snapshot: dict[str, Any],
status_cleanup_dashboard: dict[str, Any],
generated_at: str | None = None,
) -> dict[str, Any]:
"""Build a read-only market radar readback from committed evidence."""
_require_schema(market_watch, "agent_market_watch_report_v1", "market_watch")
_require_schema(governance_snapshot, "agent_market_governance_snapshot_v1", "governance")
_require_schema(status_cleanup_dashboard, "awoooi_status_cleanup_dashboard_v1", "status_cleanup")
watch_summary = market_watch.get("summary") or {}
governance_summary = governance_snapshot.get("summary") or {}
status_summary = status_cleanup_dashboard.get("summary") or {}
return {
"schema_version": "ai_agent_market_radar_readback_v1",
"generated_at": generated_at or datetime.now(timezone.utc).isoformat(),
"source_scope": {
"market_watch_report": "docs/evaluations/agent_market_watch_report_2026-06-25.json",
"market_governance_snapshot": "docs/evaluations/agent_market_governance_snapshot_2026-06-25.json",
"status_cleanup_dashboard": "docs/operations/awoooi-status-cleanup-dashboard.snapshot.json",
"project_handoff_basis": "Codex Start Here handoff generated 2026-06-25",
"gitea_main_evidence_basis_commit": "279f9531",
"scope_note": "盤點範圍涵蓋近期 Gitea 主線、治理 handoff、AI Agent market watch 與 Status Cleanup gates不包含 raw chat history。",
},
"summary": {
"overall_completion_percent": 42.2,
"status_cleanup_dashboard_percent": float(status_summary.get("overall_completion_percent", 0)),
"market_watch_completion_percent": 100.0,
"market_candidates": int(watch_summary.get("candidate_count", 0)),
"market_sources": int(watch_summary.get("source_count", 0)),
"changed_candidates": int(watch_summary.get("changed_candidates", 0)),
"source_failures": int(watch_summary.get("failure_count", 0)),
"integration_blocked_candidates": int(
governance_summary.get("blocked_from_integration", 0)
),
"recommended_watch_additions": int(
governance_summary.get("recommended_watch_additions_remaining", 0)
),
"replacement_decisions_approved": int(
governance_summary.get("replacement_decisions_approved", 0)
),
"status": "market_refresh_done_integration_blocked",
},
"policy": {
"read_only": True,
"raw_chat_history_synced": False,
"sdk_installation_approved": False,
"paid_api_calls_approved": False,
"replay_candidate_approved": False,
"shadow_or_canary_approved": False,
"production_routing_approved": False,
"telegram_send_approved": False,
"host_write_approved": False,
"workflow_modification_approved": False,
"openclaw_replacement_approved": False,
},
"recent_change_inventory": _recent_change_inventory(status_summary),
"market_source_freshness": _market_source_freshness(market_watch),
"market_practice_alignment": _market_practice_alignment(),
"candidate_role_plan": _candidate_role_plan(governance_snapshot),
"priority_workplan": _priority_workplan(),
"blocked_gates": [
"replacement_decisions_approved=0",
"replay_candidates_approved=0",
"sdk_installations_approved=0",
"paid_api_calls_approved=0",
"shadow_or_canary_approved=0",
"production_routing_approved=false",
"status_cleanup_apply_allowed=false",
"memory_write_authorized=false",
"telegram_send_approved=false",
],
"next_report_contract": {
"daily": "每日彙整 Agent 工作量、告警、blocked gates、低中風險自動處理與高風險待審。",
"weekly": "每週刷新 market watch、版本新鮮度、replay queue、成本/依賴 gate 與候選優先級。",
"monthly": "每月執行正式 market scorecard review決定是否提出 replay、shadow 或 replacement ADR。",
"human_review_required_for": [
"高風險主機寫入",
"付費 provider 或 token 上限變更",
"新 SDK / 新 MCP server / 新 runtime component",
"OpenClaw production routing replacement",
"Telegram Bot 發送策略變更",
],
"agent_auto_allowed_for": [
"read-only market watch",
"read-only package/version freshness snapshot",
"low-risk evidence aggregation",
"no-send report draft",
"offline deterministic replay fixture preparation",
],
},
}
def render_markdown(payload: dict[str, Any]) -> str:
"""Render a Traditional Chinese operator report."""
summary = payload["summary"]
lines = [
"# AI Agent 市場雷達與近期變更盤點",
"",
f"- 產生時間:`{payload['generated_at']}`",
f"- 整體治理完成度:`{summary['overall_completion_percent']}%`",
f"- 市場雷達完成度:`{summary['market_watch_completion_percent']}%`",
f"- 候選 Agent`{summary['market_candidates']}`",
f"- 官方 / 主要來源:`{summary['market_sources']}`",
f"- 來源失敗:`{summary['source_failures']}`",
f"- 需要重新審查候選:`{summary['changed_candidates']}`",
f"- 仍被整合 gate 擋下:`{summary['integration_blocked_candidates']}`",
f"- OpenClaw 取代批准:`{summary['replacement_decisions_approved']}`",
"",
"## 近期變更盤點",
"",
"| 優先級 | 工作線 | 狀態 | 進度 | 下一步 |",
"|---|---|---|---:|---|",
]
for item in payload["recent_change_inventory"]:
lines.append(
f"| `{item['priority']}` | {item['title']} | `{item['status']}` | "
f"`{item['completion_percent']}%` | {item['next_gate']} |"
)
lines.extend([
"",
"## 市場主流做法對齊",
"",
"| 做法 | AWOOOI 判定 | 下一步 |",
"|---|---|---|",
])
for practice in payload["market_practice_alignment"]:
lines.append(
f"| {practice['practice']} | `{practice['awoooi_status']}` | {practice['next_step']} |"
)
lines.extend([
"",
"## Agent 專業角色安排",
"",
"| Agent / 候選 | 建議角色 | Gate 狀態 | 下一步 |",
"|---|---|---|---|",
])
for candidate in payload["candidate_role_plan"]:
lines.append(
f"| {candidate['display_name']} | {candidate['recommended_role']} | "
f"`{candidate['gate_status']}` | {candidate['next_gate']} |"
)
lines.extend([
"",
"## 優先工作清單",
"",
"| 順序 | 工作 | 風險 | 自動化模式 | 完成定義 |",
"|---:|---|---|---|---|",
])
for item in payload["priority_workplan"]:
lines.append(
f"| {item['order']} | {item['work_item']} | `{item['risk']}` | "
f"`{item['automation_mode']}` | {item['done_definition']} |"
)
lines.extend([
"",
"## 禁止越界",
"",
])
for gate in payload["blocked_gates"]:
lines.append(f"- `{gate}`")
lines.append("")
return "\n".join(lines)
def _require_schema(payload: dict[str, Any], schema_version: str, label: str) -> None:
if payload.get("schema_version") != schema_version:
raise ValueError(f"{label}: expected {schema_version}")
def _recent_change_inventory(status_summary: dict[str, Any]) -> list[dict[str, Any]]:
return [
{
"priority": "P0",
"title": "Product Governance Owner Response Dashboard / handoff 收斂",
"status": "read_model_ready_runtime_blocked",
"completion_percent": 100,
"next_gate": "Owner questions 與 boundary acknowledgements 仍需逐項回覆。",
},
{
"priority": "P0",
"title": "Status Cleanup Dashboard read-only API 正式化",
"status": str(status_summary.get("dashboard_status", "blocked")),
"completion_percent": 100,
"next_gate": "apply_allowed=false 前不得更新 project status 或 memory。",
},
{
"priority": "P0",
"title": "Wazuh / IwoooS 可視性邊界",
"status": str(status_summary.get("wazuh_agent_visibility_status", "blocked")),
"completion_percent": 35,
"next_gate": "等待 manager agent registry readback 與 live route readback。",
},
{
"priority": "P0",
"title": "AI Agent market watch 2026-06-25",
"status": "market_refresh_done_integration_blocked",
"completion_percent": 100,
"next_gate": "更新 scorecard 並進入 offline replay gate不得直接替換。",
},
{
"priority": "P1",
"title": "日報 / 週報 / 月報數據化報告",
"status": "report_contract_defined_runtime_delivery_blocked",
"completion_percent": 65,
"next_gate": "接 Agent 工作量、Telegram receipt 與 human-review queue。",
},
{
"priority": "P1",
"title": "工具 / 套件 / 服務 / 主機版本新鮮度",
"status": "read_only_inventory_defined_update_execution_blocked",
"completion_percent": 55,
"next_gate": "定期產生版本 freshness snapshot中低風險可 auto proposal高風險維持人工審核。",
},
]
def _market_source_freshness(market_watch: dict[str, Any]) -> list[dict[str, Any]]:
interesting = {
"openai_agents_sdk_coordinator",
"langgraph_incident_kernel",
"nemo_nemotron_fabric",
"claude_agent_sdk_remediator",
"google_adk_stack",
"microsoft_agent_framework",
"crewai_flows_crews",
}
rows = []
for candidate in market_watch.get("candidates") or []:
candidate_id = str(candidate.get("candidate_id", ""))
if candidate_id not in interesting:
continue
versions = [
{
"source_id": source.get("source_id"),
"version": source.get("version"),
"published_at": source.get("published_at"),
"status": source.get("status"),
"changed": bool(source.get("changed_since_reference")),
}
for source in candidate.get("sources") or []
]
rows.append({
"candidate_id": candidate_id,
"display_name": candidate.get("display_name"),
"changed": bool(candidate.get("changed")),
"decision": candidate.get("decision"),
"versions": versions,
})
return rows
def _market_practice_alignment() -> list[dict[str, Any]]:
return [
{
"practice": "多 Agent handoff / specialist delegation",
"source": "https://openai.github.io/openai-agents-python/handoffs/",
"awoooi_status": "partially_modeled",
"next_step": "將 OpenClaw / Hermes / NemoTron handoff 事件寫入可讀 timeline。",
},
{
"practice": "Tracing / tool call / guardrail observability",
"source": "https://openai.github.io/openai-agents-python/tracing/",
"awoooi_status": "missing_unified_trace",
"next_step": "建立 Agent run trace id串接報告、Telegram receipt 與 replay outcome。",
},
{
"practice": "Durable execution / persistence / human-in-the-loop",
"source": "https://docs.langchain.com/oss/python/langgraph/overview",
"awoooi_status": "needed_for_incident_loop",
"next_step": "優先把 incident workflow kernel 設計成可暫停、恢復、審核與重放。",
},
{
"practice": "MCP / A2A / enterprise multi-agent interoperability",
"source": "https://learn.microsoft.com/en-us/agent-framework/overview/",
"awoooi_status": "watch_and_design",
"next_step": "MCP server 先做 read-only tool registry再開 write adapter。",
},
{
"practice": "Evaluation / replay / profiling before integration",
"source": "https://docs.nvidia.com/nemo/agent-toolkit/latest/index.html",
"awoooi_status": "strong_fit_for_nemotron",
"next_step": "NemoTron 維持 smoke / replay / evaluator不直接接 production routing。",
},
{
"practice": "Agent SDK as programmable code/ops remediator",
"source": "https://code.claude.com/docs/en/agent-sdk/overview",
"awoooi_status": "candidate_for_remediation_lane",
"next_step": "只允許 no-write replay 與 patch proposal禁止自動 merge / deploy。",
},
{
"practice": "Enterprise-scale ADK with evaluation and observability",
"source": "https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/adk",
"awoooi_status": "candidate_for_google_stack_review",
"next_step": "先納入 weekly watch成本與資料邊界審核後才可 adapter。",
},
]
def _candidate_role_plan(governance_snapshot: dict[str, Any]) -> list[dict[str, Any]]:
wanted = {
"openclaw_incumbent": "生產仲裁者 / production decision core",
"nemo_nemotron_fabric": "離線 replay、模型能力評估、合約輸出 smoke gate",
"hermes_agent_personal_platform": "知識記憶、證據草稿、長期技能庫候選",
"openai_agents_sdk_coordinator": "Coordinator / handoff / tracing / guardrail 候選",
"langgraph_incident_kernel": "durable incident workflow kernel 候選",
"claude_agent_sdk_remediator": "DevOps / code remediation patch proposal 候選",
"microsoft_agent_framework": "MCP / A2A enterprise workflow 候選",
"google_adk_stack": "Gemini / Vertex agent stack 候選",
"crewai_flows_crews": "快速多 Agent prototype 候選",
}
statuses = {
str(row.get("candidate_id")): row
for row in governance_snapshot.get("candidate_statuses") or []
}
rows = []
for candidate_id, role in wanted.items():
status = statuses.get(candidate_id, {})
rows.append({
"candidate_id": candidate_id,
"display_name": status.get("display_name") or candidate_id,
"recommended_role": role,
"gate_status": status.get("gate_status") or "watch_only",
"next_gate": status.get("required_next_gate")
or "continue_weekly_primary_source_market_watch",
})
return rows
def _priority_workplan() -> list[dict[str, Any]]:
return [
{
"order": 1,
"work_item": "固定每週 AI Agent market watch 並產生治理 snapshot",
"risk": "low",
"automation_mode": "agent_auto_read_only",
"done_definition": "每週一 09:00 Asia/Taipei 有 watch / integration / discovery / promotion / governance 五份 artifacts。",
},
{
"order": 2,
"work_item": "刷新 2026-06-25 market capability scorecard",
"risk": "medium",
"automation_mode": "agent_propose_owner_review",
"done_definition": "OpenAI / LangGraph / NeMo-Nemotron / Claude / Microsoft / Google / CrewAI 均有新版官方來源與分數差異。",
},
{
"order": 3,
"work_item": "建立 50 筆歷史 incident offline replay queue",
"risk": "medium",
"automation_mode": "agent_auto_prepare_human_approve_run",
"done_definition": "replay fixture 不含 secret候選結果可與 OpenClaw baseline 比較。",
},
{
"order": 4,
"work_item": "Agent 溝通 / 學習 / 成長可視化 readback",
"risk": "medium",
"automation_mode": "agent_auto_read_model",
"done_definition": "每個 Agent 的 handoff、decision、learning writeback、review score 與 blocked action 可被前端和報告讀到。",
},
{
"order": 5,
"work_item": "Telegram Bot 報告與高風險審核橋接",
"risk": "high",
"automation_mode": "human_approve_before_send_or_action",
"done_definition": "低中風險只告警回報,高風險需要 Telegram approval token / owner response 才能執行。",
},
{
"order": 6,
"work_item": "工具、套件、服務、主機版本自動 freshness 盤點",
"risk": "medium",
"automation_mode": "agent_auto_scan_agent_propose",
"done_definition": "套件、服務、主機、MCP、AI provider、模型版本都有 stale / upgrade / rollback / approval gate。",
},
]
def load_json(path: Path) -> dict[str, Any]:
with path.open(encoding="utf-8") as handle:
payload = json.load(handle)
if not isinstance(payload, dict):
raise ValueError(f"{path}: expected JSON object")
return payload
def main() -> int:
parser = argparse.ArgumentParser(description="Build AI Agent market radar readback.")
parser.add_argument("--market-watch", required=True)
parser.add_argument("--governance-snapshot", required=True)
parser.add_argument("--status-cleanup-dashboard", required=True)
parser.add_argument("--output", required=True)
parser.add_argument("--markdown-output", required=True)
args = parser.parse_args()
payload = build_radar(
market_watch=load_json(Path(args.market_watch)),
governance_snapshot=load_json(Path(args.governance_snapshot)),
status_cleanup_dashboard=load_json(Path(args.status_cleanup_dashboard)),
)
Path(args.output).write_text(
json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
encoding="utf-8",
)
markdown = render_markdown(payload)
Path(args.markdown_output).write_text(markdown, encoding="utf-8")
print(
"AI_AGENT_MARKET_RADAR_READBACK_OK "
f"overall={payload['summary']['overall_completion_percent']}% "
f"candidates={payload['summary']['market_candidates']} "
f"sources={payload['summary']['market_sources']} "
f"changed={payload['summary']['changed_candidates']} "
f"blocked={payload['summary']['integration_blocked_candidates']} "
f"replacement={payload['summary']['replacement_decisions_approved']}"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())