154 lines
6.7 KiB
Python
154 lines
6.7 KiB
Python
"""Web UI dashboard model for Architect Governance Agent.
|
|
|
|
Shows requirement changes, architecture review findings, document refresh status,
|
|
deployment consistency, test case readiness, weekly research and V/R/C version
|
|
recommendations.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import asdict, dataclass, field
|
|
from datetime import datetime, timezone
|
|
from typing import Any
|
|
|
|
|
|
def utc_now() -> str:
|
|
return datetime.now(timezone.utc).isoformat()
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ArchitectPanelMetric:
|
|
key: str
|
|
title: str
|
|
value: Any
|
|
status: str = "ok"
|
|
detail: str = ""
|
|
|
|
def to_dict(self) -> dict[str, Any]:
|
|
return asdict(self)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ArchitectPanel:
|
|
key: str
|
|
title: str
|
|
description: str
|
|
metrics: list[ArchitectPanelMetric] = field(default_factory=list)
|
|
|
|
def to_dict(self) -> dict[str, Any]:
|
|
return {
|
|
"key": self.key,
|
|
"title": self.title,
|
|
"description": self.description,
|
|
"metrics": [m.to_dict() for m in self.metrics],
|
|
}
|
|
|
|
|
|
class ArchitectGovernanceDashboard:
|
|
def overview(
|
|
self,
|
|
requirement_changes: list[dict[str, Any]] | None = None,
|
|
architecture_reviews: list[dict[str, Any]] | None = None,
|
|
document_status: dict[str, Any] | None = None,
|
|
research_status: dict[str, Any] | None = None,
|
|
version_recommendations: list[dict[str, Any]] | None = None,
|
|
) -> dict[str, Any]:
|
|
requirement_changes = requirement_changes or []
|
|
architecture_reviews = architecture_reviews or []
|
|
document_status = document_status or {}
|
|
research_status = research_status or {}
|
|
version_recommendations = version_recommendations or []
|
|
panels = [
|
|
self.requirement_panel(requirement_changes),
|
|
self.architecture_panel(architecture_reviews),
|
|
self.document_panel(document_status),
|
|
self.research_panel(research_status),
|
|
self.version_panel(version_recommendations),
|
|
]
|
|
return {
|
|
"module": "architect-governance",
|
|
"route": "/admin/ai-evolution/architect",
|
|
"title": "架构师 Agent 治理中心",
|
|
"status": "attention_required" if any(self._panel_warn(panel) for panel in panels) else "healthy",
|
|
"generated_at": utc_now(),
|
|
"panels": [panel.to_dict() for panel in panels],
|
|
"requirement_changes": requirement_changes,
|
|
"architecture_reviews": architecture_reviews,
|
|
"version_recommendations": version_recommendations,
|
|
}
|
|
|
|
def requirement_panel(self, changes: list[dict[str, Any]]) -> ArchitectPanel:
|
|
return ArchitectPanel(
|
|
key="requirements",
|
|
title="需求变化记录",
|
|
description="记录来自 Custom GPT、Codex、OpenClaw、Hermes 和用户反馈的需求变化。",
|
|
metrics=[
|
|
ArchitectPanelMetric("total_requirement_changes", "需求变化数量", len(changes)),
|
|
ArchitectPanelMetric(
|
|
"undocumented_changes",
|
|
"待刷新到用户需求文档",
|
|
len([c for c in changes if not c.get("documented")]),
|
|
"warn" if any(not c.get("documented") for c in changes) else "ok",
|
|
),
|
|
],
|
|
)
|
|
|
|
def architecture_panel(self, reviews: list[dict[str, Any]]) -> ArchitectPanel:
|
|
pending = [r for r in reviews if r.get("status") not in {"pass", "not_required"}]
|
|
return ArchitectPanel(
|
|
key="architecture_review",
|
|
title="全量架构审视",
|
|
description="展示架构一致性、扩展性、安全边界、可运维性和回滚策略审查。",
|
|
metrics=[
|
|
ArchitectPanelMetric("review_count", "架构审查数量", len(reviews)),
|
|
ArchitectPanelMetric("pending_reviews", "待处理架构审查", len(pending), "warn" if pending else "ok"),
|
|
],
|
|
)
|
|
|
|
def document_panel(self, status: dict[str, Any]) -> ArchitectPanel:
|
|
required_docs = ["requirements", "architecture", "deployment", "test_cases"]
|
|
missing = [doc for doc in required_docs if status.get(doc) not in {"ready", "updated"}]
|
|
return ArchitectPanel(
|
|
key="documents",
|
|
title="文档版本化状态",
|
|
description="用户需求、架构设计、工程部署、测试例文档刷新状态。",
|
|
metrics=[
|
|
ArchitectPanelMetric("requirements_doc", "用户需求文档", status.get("requirements", "unknown"), "warn" if "requirements" in missing else "ok"),
|
|
ArchitectPanelMetric("architecture_doc", "架构设计文档", status.get("architecture", "unknown"), "warn" if "architecture" in missing else "ok"),
|
|
ArchitectPanelMetric("deployment_doc", "工程部署文档", status.get("deployment", "unknown"), "warn" if "deployment" in missing else "ok"),
|
|
ArchitectPanelMetric("test_case_doc", "测试例文档", status.get("test_cases", "unknown"), "warn" if "test_cases" in missing else "ok"),
|
|
],
|
|
)
|
|
|
|
def research_panel(self, status: dict[str, Any]) -> ArchitectPanel:
|
|
overdue = bool(status.get("overdue"))
|
|
return ArchitectPanel(
|
|
key="weekly_research",
|
|
title="每周外部技术情报",
|
|
description="联网搜索 Agent/模型版本、GitHub top 实现、潜在安全影响。",
|
|
metrics=[
|
|
ArchitectPanelMetric("last_research_at", "最近调研时间", status.get("last_research_at", "never"), "warn" if overdue else "ok"),
|
|
ArchitectPanelMetric("findings", "发现数量", status.get("findings", 0)),
|
|
ArchitectPanelMetric("optimization_candidates", "可借鉴优化项", status.get("optimization_candidates", 0)),
|
|
],
|
|
)
|
|
|
|
def version_panel(self, recommendations: list[dict[str, Any]]) -> ArchitectPanel:
|
|
latest = recommendations[-1] if recommendations else {}
|
|
return ArchitectPanel(
|
|
key="version_decision",
|
|
title="V/R/C 版本建议",
|
|
description="由架构师 Agent 判断变更应进入 C、R 或 V。",
|
|
metrics=[
|
|
ArchitectPanelMetric("recommendation_count", "版本建议数量", len(recommendations)),
|
|
ArchitectPanelMetric("latest_recommendation", "最近建议", latest.get("version_bump", "none")),
|
|
ArchitectPanelMetric("reason", "建议原因", latest.get("reason", "")),
|
|
],
|
|
)
|
|
|
|
def _panel_warn(self, panel: ArchitectPanel) -> bool:
|
|
return any(metric.status == "warn" for metric in panel.metrics)
|
|
|
|
|
|
__all__ = ["ArchitectPanelMetric", "ArchitectPanel", "ArchitectGovernanceDashboard"]
|