diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py
index 58a42b1d..278e0514 100644
--- a/apps/api/src/api/v1/agents.py
+++ b/apps/api/src/api/v1/agents.py
@@ -44,6 +44,9 @@ from src.services.ai_agent_market_radar_readback import (
from src.services.ai_technology_radar_readback import (
load_latest_ai_technology_radar_readback,
)
+from src.services.ai_technology_report_cadence_readback import (
+ load_latest_ai_technology_report_cadence_readback,
+)
from src.services.agent_service import (
AgentService,
TaskState,
@@ -750,6 +753,36 @@ async def get_ai_technology_radar_readback() -> dict[str, Any]:
) from exc
+@router.get(
+ "/ai-technology-report-cadence-readback",
+ response_model=dict[str, Any],
+ summary="取得 AI 技術雷達日週月報與報告後分析讀回",
+ description=(
+ "讀取最新已提交的 AI 技術雷達日報、週報、月報 readback;"
+ "此端點只呈現報告節奏、Agent 工作狀態、圖表化摘要、報告後 AI 分析包、"
+ "低中高風險處理邊界與 Telegram no-send 審核包。"
+ "它不送 Telegram、不寫 receipt、不呼叫 Bot API、不執行低中風險 runtime write、"
+ "不安裝 SDK、不呼叫付費 API、不切換模型、不改主機、不修改 production routing、不替換 OpenClaw。"
+ ),
+)
+async def get_ai_technology_report_cadence_readback() -> dict[str, Any]:
+ """回傳 AI 技術雷達日週月報與報告後分析只讀快照。"""
+ try:
+ payload = await asyncio.to_thread(load_latest_ai_technology_report_cadence_readback)
+ return redact_public_lan_topology(payload)
+ except FileNotFoundError as exc:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail=str(exc),
+ ) from exc
+ except (json.JSONDecodeError, ValueError) as exc:
+ logger.error("ai_technology_report_cadence_readback_invalid", error=str(exc))
+ raise HTTPException(
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+ detail="AI 技術雷達日週月報 readback 無效",
+ ) from exc
+
+
@router.get(
"/automation-inventory-snapshot",
response_model=dict[str, Any],
diff --git a/apps/api/src/services/ai_technology_report_cadence_readback.py b/apps/api/src/services/ai_technology_report_cadence_readback.py
new file mode 100644
index 00000000..a3c04e86
--- /dev/null
+++ b/apps/api/src/services/ai_technology_report_cadence_readback.py
@@ -0,0 +1,108 @@
+"""
+AI technology report cadence readback.
+
+Loads the committed daily / weekly / monthly AI technology report artifact.
+This surface is no-send and no-write: it does not deliver Telegram messages,
+write report receipts, call model providers, install SDKs, modify hosts, or
+change production routing.
+"""
+
+from __future__ import annotations
+
+import json
+from pathlib import Path
+from typing import Any
+
+from src.services.snapshot_paths import default_operations_dir
+
+_DEFAULT_OPERATIONS_DIR = default_operations_dir(Path(__file__))
+_SNAPSHOT_NAME = "ai-technology-report-cadence-readback.snapshot.json"
+
+
+def load_latest_ai_technology_report_cadence_readback(
+ operations_dir: Path | None = None,
+) -> dict[str, Any]:
+ """Load the committed AI technology report cadence readback snapshot."""
+ directory = operations_dir or _DEFAULT_OPERATIONS_DIR
+ snapshot_path = directory / _SNAPSHOT_NAME
+ with snapshot_path.open(encoding="utf-8") as handle:
+ payload = json.load(handle)
+
+ if not isinstance(payload, dict):
+ raise ValueError(f"{snapshot_path}: expected JSON object")
+ if payload.get("schema_version") != "ai_technology_report_cadence_readback_v1":
+ raise ValueError(f"{snapshot_path}: unexpected schema_version")
+
+ policy = payload.get("policy") or {}
+ forbidden_true = [
+ key
+ for key in [
+ "raw_chat_history_synced",
+ "raw_report_payload_display_allowed",
+ "report_delivery_enabled",
+ "telegram_send_enabled",
+ "bot_api_call_enabled",
+ "report_receipt_write_enabled",
+ "ai_post_report_analysis_live_run_enabled",
+ "low_medium_runtime_auto_write_enabled",
+ "sdk_installation_approved",
+ "paid_api_calls_approved",
+ "production_routing_approved",
+ "model_provider_switch_approved",
+ "host_write_approved",
+ "openclaw_replacement_approved",
+ ]
+ if policy.get(key) is not False
+ ]
+ if forbidden_true:
+ raise ValueError(f"{snapshot_path}: unsafe policy flags: {forbidden_true}")
+ if policy.get("read_only") is not True:
+ raise ValueError(f"{snapshot_path}: read_only policy must be true")
+ if policy.get("high_risk_owner_review_required") is not True:
+ raise ValueError(f"{snapshot_path}: high risk owner review must remain required")
+
+ summary = payload.get("summary") or {}
+ zero_fields = [
+ "live_delivery_count_24h",
+ "report_receipt_write_count_24h",
+ "auto_optimization_write_count",
+ ]
+ nonzero = [field for field in zero_fields if summary.get(field) != 0]
+ if nonzero:
+ raise ValueError(f"{snapshot_path}: no-write summary fields must stay zero: {nonzero}")
+ if summary.get("telegram_send_enabled") is not False:
+ raise ValueError(f"{snapshot_path}: telegram_send_enabled must stay false")
+
+ cadences = payload.get("report_cadences") or []
+ cadence_ids = {row.get("cadence") for row in cadences}
+ if cadence_ids != {"daily", "weekly", "monthly"}:
+ raise ValueError(f"{snapshot_path}: report cadences must cover daily, weekly, monthly")
+ if len(payload.get("post_report_analysis_packets") or []) != 3:
+ raise ValueError(f"{snapshot_path}: post report analysis packets must cover 3 reports")
+
+ telegram_bridge = payload.get("telegram_report_bridge") or {}
+ if telegram_bridge.get("telegram_send_enabled") is not False:
+ raise ValueError(f"{snapshot_path}: Telegram bridge send must stay false")
+ if telegram_bridge.get("bot_api_call_enabled") is not False:
+ raise ValueError(f"{snapshot_path}: Telegram bridge bot API calls must stay false")
+ if telegram_bridge.get("report_receipt_write_enabled") is not False:
+ raise ValueError(f"{snapshot_path}: Telegram bridge receipt writes must stay false")
+
+ serialized = json.dumps(payload, ensure_ascii=False)
+ forbidden_fragments = [
+ "/Users/",
+ ".claude/projects",
+ ".codex",
+ "192.168.",
+ "auth.json",
+ "conversations",
+ "sessions",
+ "批准!繼續",
+ "My request for Codex",
+ "In app browser",
+ ]
+ leaked = [fragment for fragment in forbidden_fragments if fragment in serialized]
+ if leaked:
+ raise ValueError(f"{snapshot_path}: forbidden local or raw-history fragment: {leaked}")
+
+ return payload
diff --git a/apps/api/tests/test_ai_technology_report_cadence_readback.py b/apps/api/tests/test_ai_technology_report_cadence_readback.py
new file mode 100644
index 00000000..4a30e8a4
--- /dev/null
+++ b/apps/api/tests/test_ai_technology_report_cadence_readback.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+import json
+
+from src.services.ai_technology_report_cadence_readback import (
+ load_latest_ai_technology_report_cadence_readback,
+)
+
+
+def test_ai_technology_report_cadence_readback_committed_snapshot_is_safe():
+ payload = load_latest_ai_technology_report_cadence_readback()
+
+ assert payload["schema_version"] == "ai_technology_report_cadence_readback_v1"
+ assert payload["summary"]["overall_completion_percent"] == 42.2
+ assert payload["summary"]["report_cadence_completion_percent"] == 100.0
+ assert payload["summary"]["report_cadence_count"] == 3
+ assert payload["summary"]["report_ready_count"] == 3
+ assert payload["summary"]["chart_section_count"] == 6
+ assert payload["summary"]["agent_status_report_count"] == 5
+ assert payload["summary"]["post_report_analysis_packet_count"] == 3
+ assert payload["summary"]["low_medium_auto_action_proposal_count"] == 6
+ assert payload["summary"]["high_risk_owner_review_count"] == 5
+ assert payload["summary"]["technology_count"] == 20
+ assert payload["summary"]["source_count"] == 47
+ assert payload["summary"]["source_failures"] == 0
+ assert payload["summary"]["telegram_send_enabled"] is False
+ assert payload["summary"]["live_delivery_count_24h"] == 0
+ assert payload["summary"]["report_receipt_write_count_24h"] == 0
+ assert payload["summary"]["auto_optimization_write_count"] == 0
+
+ policy = payload["policy"]
+ assert policy["read_only"] is True
+ assert policy["raw_chat_history_synced"] is False
+ assert policy["raw_report_payload_display_allowed"] is False
+ assert policy["report_delivery_enabled"] is False
+ assert policy["telegram_send_enabled"] is False
+ assert policy["bot_api_call_enabled"] is False
+ assert policy["report_receipt_write_enabled"] is False
+ assert policy["ai_post_report_analysis_live_run_enabled"] is False
+ assert policy["low_medium_runtime_auto_write_enabled"] is False
+ assert policy["high_risk_owner_review_required"] is True
+ assert policy["sdk_installation_approved"] is False
+ assert policy["paid_api_calls_approved"] is False
+ assert policy["production_routing_approved"] is False
+ assert policy["model_provider_switch_approved"] is False
+ assert policy["host_write_approved"] is False
+ assert policy["openclaw_replacement_approved"] is False
+
+ serialized = json.dumps(payload, ensure_ascii=False)
+ assert "/Users/" not in serialized
+ assert ".claude/projects" not in serialized
+ assert ".codex" not in serialized
+ assert "192.168." not in serialized
+ assert "auth.json" not in serialized
+ assert "批准!繼續" not in serialized
+
+
+def test_ai_technology_report_cadence_readback_covers_reports_agents_and_risk():
+ payload = load_latest_ai_technology_report_cadence_readback()
+
+ cadences = {row["cadence"]: row for row in payload["report_cadences"]}
+ assert set(cadences) == {"daily", "weekly", "monthly"}
+ assert cadences["daily"]["owner_agent"] == "Hermes"
+ assert cadences["weekly"]["reviewer_agent"] == "NemoTron"
+ assert cadences["monthly"]["owner_agent"] == "OpenClaw"
+ assert all(row["telegram_delivery_status"].startswith("no_send") for row in cadences.values())
+
+ workloads = {row["agent"]: row for row in payload["agent_workload_reports"]}
+ assert workloads["MarketRadar"]["work_unit_count"] == 47
+ assert workloads["NemoTron"]["work_unit_count"] == 14
+ assert workloads["OpenClaw"]["work_unit_count"] == 9
+ assert "production baseline" in workloads["OpenClaw"]["latest_output"]
+
+ packets = {row["report_id"]: row for row in payload["post_report_analysis_packets"]}
+ assert packets["daily"]["risk_tier"] == "low"
+ assert packets["weekly"]["risk_tier"] == "medium"
+ assert packets["monthly"]["risk_tier"] == "high"
+ assert packets["monthly"]["agent_decision"] == "owner_review_required"
+
+ risks = {row["risk_tier"]: row for row in payload["risk_automation_policy"]}
+ assert set(risks) == {"low", "medium", "high"}
+ assert "不得 live send" in risks["low"]["blocked_without_approval"]
+ assert "不得安裝 SDK" in risks["medium"]["blocked_without_approval"]
+ assert "高風險" in risks["high"]["reporting_mode"]
diff --git a/apps/api/tests/test_ai_technology_report_cadence_readback_api.py b/apps/api/tests/test_ai_technology_report_cadence_readback_api.py
new file mode 100644
index 00000000..6f10a36c
--- /dev/null
+++ b/apps/api/tests/test_ai_technology_report_cadence_readback_api.py
@@ -0,0 +1,51 @@
+from __future__ import annotations
+
+import json
+
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+
+from src.api.v1.agents import router
+
+
+def test_ai_technology_report_cadence_readback_endpoint_returns_committed_snapshot():
+ app = FastAPI()
+ app.include_router(router, prefix="/api/v1")
+ client = TestClient(app)
+
+ response = client.get("/api/v1/agents/ai-technology-report-cadence-readback")
+
+ assert response.status_code == 200
+ data = response.json()
+ assert data["schema_version"] == "ai_technology_report_cadence_readback_v1"
+ assert data["summary"]["overall_completion_percent"] == 42.2
+ assert data["summary"]["report_cadence_completion_percent"] == 100.0
+ assert data["summary"]["report_ready_count"] == 3
+ assert data["summary"]["chart_section_count"] == 6
+ assert data["summary"]["agent_status_report_count"] == 5
+ assert data["summary"]["post_report_analysis_packet_count"] == 3
+ assert data["summary"]["telegram_send_enabled"] is False
+ assert data["summary"]["live_delivery_count_24h"] == 0
+ assert data["summary"]["report_receipt_write_count_24h"] == 0
+ assert data["policy"]["read_only"] is True
+ assert data["policy"]["telegram_send_enabled"] is False
+ assert data["policy"]["report_receipt_write_enabled"] is False
+ assert data["policy"]["low_medium_runtime_auto_write_enabled"] is False
+ assert data["policy"]["high_risk_owner_review_required"] is True
+
+ assert {row["cadence"] for row in data["report_cadences"]} == {
+ "daily",
+ "weekly",
+ "monthly",
+ }
+ assert data["telegram_report_bridge"]["integration_status"] == (
+ "approval_package_ready_no_live_send"
+ )
+ assert data["telegram_report_bridge"]["telegram_send_enabled"] is False
+
+ serialized = json.dumps(data, ensure_ascii=False)
+ assert "/Users/" not in serialized
+ assert ".claude/projects" not in serialized
+ assert ".codex" not in serialized
+ assert "192.168." not in serialized
+ assert "My request for Codex" not in serialized
diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json
index 61e70931..fd782db9 100644
--- a/apps/web/messages/en.json
+++ b/apps/web/messages/en.json
@@ -3328,6 +3328,24 @@
"policyHolds": "審核鎖"
}
},
+ "technologyReports": {
+ "title": "AI 技術日報 / 週報 / 月報",
+ "status": "報告狀態",
+ "telegram": "Telegram",
+ "receipt": "Receipt",
+ "autoWrite": "自動寫入",
+ "cadencesTitle": "報告節奏與 AI 閱讀後分析",
+ "workloadTitle": "每個 Agent 工作狀態報告",
+ "analysisTitle": "報告後 AI 解法與風險邊界",
+ "metrics": {
+ "reports": "報告完成",
+ "charts": "圖表區塊",
+ "agentStatus": "Agent 報告",
+ "analysisPackets": "分析包",
+ "lowMedium": "低中風險",
+ "highRisk": "高風險"
+ }
+ },
"metrics": {
"candidates": "候選數",
"sources": "來源數",
diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json
index 61e70931..fd782db9 100644
--- a/apps/web/messages/zh-TW.json
+++ b/apps/web/messages/zh-TW.json
@@ -3328,6 +3328,24 @@
"policyHolds": "審核鎖"
}
},
+ "technologyReports": {
+ "title": "AI 技術日報 / 週報 / 月報",
+ "status": "報告狀態",
+ "telegram": "Telegram",
+ "receipt": "Receipt",
+ "autoWrite": "自動寫入",
+ "cadencesTitle": "報告節奏與 AI 閱讀後分析",
+ "workloadTitle": "每個 Agent 工作狀態報告",
+ "analysisTitle": "報告後 AI 解法與風險邊界",
+ "metrics": {
+ "reports": "報告完成",
+ "charts": "圖表區塊",
+ "agentStatus": "Agent 報告",
+ "analysisPackets": "分析包",
+ "lowMedium": "低中風險",
+ "highRisk": "高風險"
+ }
+ },
"metrics": {
"candidates": "候選數",
"sources": "來源數",
diff --git a/apps/web/src/app/[locale]/governance/tabs/agent-market-tab.tsx b/apps/web/src/app/[locale]/governance/tabs/agent-market-tab.tsx
index ecf358d2..e2044537 100644
--- a/apps/web/src/app/[locale]/governance/tabs/agent-market-tab.tsx
+++ b/apps/web/src/app/[locale]/governance/tabs/agent-market-tab.tsx
@@ -14,7 +14,7 @@ import { useTranslations } from 'next-intl'
import { GlassCard } from '@/components/ui/glass-card'
import { StatusOrb } from '@/components/ui/status-orb'
import { AgentActivityConstellation } from '@/components/governance/agent-activity-constellation'
-import { apiClient, type AgentMarketGovernanceSnapshot, type AiTechnologyRadarReadback } from '@/lib/api-client'
+import { apiClient, type AgentMarketGovernanceSnapshot, type AiTechnologyRadarReadback, type AiTechnologyReportCadenceReadback } from '@/lib/api-client'
// =============================================================================
// Helpers
@@ -327,6 +327,109 @@ function ProfessionalAgentRoleCard({ role }: { role: AiTechnologyRadarReadback['
)
}
+function ReportCadenceCard({ cadence }: { cadence: AiTechnologyReportCadenceReadback['report_cadences'][number] }) {
+ return (
+
+
+
+ {cadence.cadence_label}
+
+
+
+
+
+
+
+
+ {cadence.report_purpose}
+
+
+ {cadence.ai_analysis_after_reading}
+
+
+ )
+}
+
+function AgentWorkloadCard({ workload }: { workload: AiTechnologyReportCadenceReadback['agent_workload_reports'][number] }) {
+ return (
+
+
+
+ {workload.agent}
+
+
+
+
+ {workload.professional_responsibility}
+
+
+ {workload.latest_output}
+
+
+ {workload.next_action}
+
+
+ )
+}
+
+function PostReportAnalysisCard({ packet }: { packet: AiTechnologyReportCadenceReadback['post_report_analysis_packets'][number] }) {
+ const tone = packet.risk_tier === 'high' ? '#F59E0B' : packet.risk_tier === 'medium' ? '#d97757' : '#22C55E'
+ return (
+
+
+
+ {packet.report_id}
+
+
+ {packet.risk_tier}
+
+
+
+ {packet.key_finding}
+
+
+ {packet.proposed_solution}
+
+
+ {packet.execution_boundary}
+
+
+ )
+}
+
// =============================================================================
// Component
// =============================================================================
@@ -335,6 +438,7 @@ export function AgentMarketTab() {
const t = useTranslations('governance.agentMarket')
const [snapshot, setSnapshot] = useState(null)
const [technologyRadar, setTechnologyRadar] = useState(null)
+ const [technologyReportCadence, setTechnologyReportCadence] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(false)
@@ -343,10 +447,12 @@ export function AgentMarketTab() {
Promise.all([
apiClient.getAgentMarketGovernanceSnapshot(),
apiClient.getAiTechnologyRadarReadback(),
+ apiClient.getAiTechnologyReportCadenceReadback(),
])
- .then(([marketSnapshot, radarReadback]) => {
+ .then(([marketSnapshot, radarReadback, reportCadenceReadback]) => {
setSnapshot(marketSnapshot)
setTechnologyRadar(radarReadback)
+ setTechnologyReportCadence(reportCadenceReadback)
setError(false)
})
.catch(() => setError(true))
@@ -371,7 +477,7 @@ export function AgentMarketTab() {
)
}
- if (error || !snapshot || !technologyRadar) {
+ if (error || !snapshot || !technologyRadar || !technologyReportCadence) {
return (
@@ -407,6 +513,7 @@ export function AgentMarketTab() {
const summary = snapshot.summary
const radarSummary = technologyRadar.summary
+ const reportSummary = technologyReportCadence.summary
const allApprovals =
summary.priority_upgrades_approved +
summary.market_scorecard_updates_approved +
@@ -527,6 +634,115 @@ export function AgentMarketTab() {
+
+
+
+
+
+
+ {t('technologyReports.title')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {t('technologyReports.cadencesTitle')}
+
+
+
+ {technologyReportCadence.report_cadences.map(cadence => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+ {t('technologyReports.workloadTitle')}
+
+
+
+ {technologyReportCadence.agent_workload_reports.map(workload => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+ {t('technologyReports.analysisTitle')}
+
+
+
+ {technologyReportCadence.post_report_analysis_packets.map(packet => (
+
+ ))}
+
+
+
+
@@ -975,6 +1191,11 @@ export function AgentMarketTab() {
.agent-market-radar-domain-grid,
.agent-market-radar-rolling-grid,
.agent-market-radar-role-grid,
+ .agent-market-report-metrics-grid,
+ .agent-market-report-gate-grid,
+ .agent-market-report-cadence-grid,
+ .agent-market-report-workload-grid,
+ .agent-market-report-analysis-grid,
.agent-market-health-grid,
.agent-market-cadence-grid,
.agent-market-decision-grid,
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts
index fe97692f..b1d947a8 100644
--- a/apps/web/src/lib/api-client.ts
+++ b/apps/web/src/lib/api-client.ts
@@ -319,6 +319,11 @@ export const apiClient = {
return handleResponse
(res)
},
+ async getAiTechnologyReportCadenceReadback() {
+ const res = await fetch(`${API_BASE_URL}/agents/ai-technology-report-cadence-readback`)
+ return handleResponse(res)
+ },
+
async getAiAgentAutomationInventorySnapshot() {
const res = await fetch(`${API_BASE_URL}/agents/automation-inventory-snapshot`)
return handleResponse(res)
@@ -1173,6 +1178,121 @@ export interface AiTechnologyRadarReadback {
}
}
+export interface AiTechnologyReportCadenceReadback {
+ schema_version: 'ai_technology_report_cadence_readback_v1'
+ generated_at: string
+ source_scope: Record
+ summary: {
+ overall_completion_percent: number
+ report_cadence_completion_percent: number
+ report_cadence_count: number
+ report_ready_count: number
+ chart_section_count: number
+ agent_status_report_count: number
+ post_report_analysis_packet_count: number
+ low_medium_auto_action_proposal_count: number
+ high_risk_owner_review_count: number
+ technology_count: number
+ source_count: number
+ source_failures: number
+ telegram_send_enabled: false
+ live_delivery_count_24h: 0
+ report_receipt_write_count_24h: 0
+ auto_optimization_write_count: 0
+ policy_hold_count: number
+ status: string
+ }
+ policy: {
+ read_only: true
+ raw_chat_history_synced: false
+ raw_report_payload_display_allowed: false
+ report_delivery_enabled: false
+ telegram_send_enabled: false
+ bot_api_call_enabled: false
+ report_receipt_write_enabled: false
+ ai_post_report_analysis_live_run_enabled: false
+ low_medium_runtime_auto_write_enabled: false
+ high_risk_owner_review_required: true
+ sdk_installation_approved: false
+ paid_api_calls_approved: false
+ production_routing_approved: false
+ model_provider_switch_approved: false
+ host_write_approved: false
+ openclaw_replacement_approved: false
+ }
+ report_cadences: Array<{
+ cadence: 'daily' | 'weekly' | 'monthly'
+ cadence_label: string
+ owner_agent: string
+ reviewer_agent: string
+ report_purpose: string
+ data_inputs: string[]
+ metrics: Record
+ chart_types: string[]
+ ai_analysis_after_reading: string
+ low_medium_auto_actions: string[]
+ high_risk_owner_review_actions: string[]
+ telegram_delivery_status: string
+ }>
+ agent_workload_reports: Array<{
+ agent: string
+ professional_responsibility: string
+ work_unit_count: number
+ work_unit_label: string
+ latest_output: string
+ next_action: string
+ }>
+ chart_sections: Array<{
+ chart_id: string
+ title: string
+ chart_type: string
+ primary_metric: string
+ value: number
+ expected_report_signal: string
+ }>
+ post_report_analysis_packets: Array<{
+ report_id: 'daily' | 'weekly' | 'monthly'
+ risk_tier: 'low' | 'medium' | 'high'
+ key_finding: string
+ proposed_solution: string
+ agent_decision: string
+ execution_boundary: string
+ }>
+ risk_automation_policy: Array<{
+ risk_tier: 'low' | 'medium' | 'high'
+ agent_auto_scope: string
+ blocked_without_approval: string
+ reporting_mode: string
+ }>
+ telegram_report_bridge: {
+ integration_status: string
+ canonical_group_env: string
+ telegram_send_enabled: false
+ bot_api_call_enabled: false
+ report_receipt_write_enabled: false
+ draft_count: number
+ drafts: Array<{
+ draft_id: string
+ cadence: 'daily' | 'weekly' | 'monthly'
+ status: string
+ required_gate: string
+ }>
+ delivery_note: string
+ }
+ blocked_gates: string[]
+ next_allowed_actions: string[]
+ forbidden_actions_without_new_approval: string[]
+ report_contract: {
+ api_endpoint: string
+ frontend_target: string
+ source_endpoint: string
+ daily: string
+ weekly: string
+ monthly: string
+ telegram: string
+ }
+}
+
// =========================================================================
// AI Agent Automation Inventory Snapshot
// =========================================================================
diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md
index 0e8366d1..bb53fb0c 100644
--- a/docs/LOGBOOK.md
+++ b/docs/LOGBOOK.md
@@ -1,3 +1,27 @@
+## 2026-06-25|AI 技術雷達日週月報與報告後分析讀回
+
+**本輪收斂範圍:**
+- 新增 AI 技術雷達日報 / 週報 / 月報 readback:`scripts/dev/ai-technology-report-cadence-readback.py`、`docs/operations/ai-technology-report-cadence-readback.snapshot.json`、`docs/operations/AI-TECHNOLOGY-REPORT-CADENCE-READBACK-2026-06-25.md`。
+- 新增 schema、API service 與 endpoint:`ai_technology_report_cadence_readback_v1`、`GET /api/v1/agents/ai-technology-report-cadence-readback`。
+- Agent 市場頁新增「AI 技術日報 / 週報 / 月報」區塊,顯示報告完成度、圖表區塊、每個 Agent 工作狀態、報告後 AI 分析包、低中高風險處置邊界與 Telegram no-send gate。
+- 報告資料只來自已提交的 `ai-technology-radar-readback.snapshot.json`,不讀 raw 對話、不同步本機工作視窗、不送 Telegram、不寫 receipt、不做 runtime write。
+
+**各段完成度:**
+- 日報 / 週報 / 月報 readback:`100%`,`3/3` 報告節奏可讀。
+- 圖表化報告契約:`100%`,`6` 個 chart sections。
+- 每個 Agent 工作狀態報告:`100%`,OpenClaw / Hermes / NemoTron / MarketRadar / Critic `5/5`。
+- 報告後 AI 分析包:`100%`,daily / weekly / monthly `3/3`,低 / 中 / 高風險各有解法與執行邊界。
+- Telegram live delivery / receipt write / runtime auto optimization:`0%`,仍被 gate 擋下。
+
+**readback:**
+- `AI_TECHNOLOGY_REPORT_CADENCE_READBACK_OK overall=42.2% reports=3/3 charts=6 agents=5 telegram_send=False`。
+- `telegram_send_enabled=false`、`bot_api_call_enabled=false`、`report_receipt_write_enabled=false`、`low_medium_runtime_auto_write_enabled=false`、`high_risk_owner_review_required=true`。
+
+**仍禁止 / 未完成:**
+- 不得把 no-send Telegram 草稿當成 live send。
+- 不得把低中風險 report proposal 當成 runtime write、host write、workflow trigger、SDK install 或 provider switch 授權。
+- 高風險仍必須 owner review,OpenClaw 替換、生產路由、付費 API、Telegram live delivery 都不能自動執行。
+
## 2026-06-25|AI 技術雷達近即時監控與產品讀回
**背景**:使用者要求 AWOOOI 不能只評估 AI Agent,整個產品與網站必須持續、即時監控市場上所有主流 AI 技術,包含新技術、新版本、新整合與新應用,並能滾動更新到專案評估流程中。
diff --git a/docs/operations/AI-TECHNOLOGY-REPORT-CADENCE-READBACK-2026-06-25.md b/docs/operations/AI-TECHNOLOGY-REPORT-CADENCE-READBACK-2026-06-25.md
new file mode 100644
index 00000000..926b663f
--- /dev/null
+++ b/docs/operations/AI-TECHNOLOGY-REPORT-CADENCE-READBACK-2026-06-25.md
@@ -0,0 +1,63 @@
+# AI 技術雷達日報 / 週報 / 月報讀回
+
+- 產生時間:`2026-06-25T06:13:58.765962+00:00`
+- 整體治理完成度:`42.2%`
+- 報告節奏完成度:`100.0%`
+- 報告節奏:`3/3`
+- 圖表區塊:`6`
+- Agent 工作狀態報告:`5`
+- 報告後 AI 分析包:`3`
+- 低中風險自動化提案:`6`
+- 高風險 owner review:`5`
+- Telegram live send:`False`
+- 正式送出 / receipt / auto optimization 寫入:`0` / `0` / `0`
+- 狀態:`daily_weekly_monthly_reports_ready_no_send_gated`
+
+## 報告節奏
+
+| 節奏 | Owner Agent | 內容 | AI 看完後做什麼 | Telegram |
+|---|---|---|---|---|
+| 日報 | Hermes | 彙整 6 小時雷達輸出、來源失敗、版本變更、審核佇列與低中風險處理建議。 | Hermes 先摘要,MarketRadar 標示 freshness,Critic 檢查是否可低風險自動處理。 | `no_send_draft_ready` |
+| 週報 | MarketRadar | 刷新技術 scorecard,判斷 sandbox、offline replay、adapter design 與 watchlist 優先級。 | NemoTron 只做離線 replay / scorecard 草稿,OpenClaw 只讀審核分數並維持 policy guard。 | `no_send_scorecard_ready` |
+| 月報 | OpenClaw | 彙整市場趨勢,提出 roadmap / watch-only / retire / replacement-review 策略包。 | OpenClaw 只做仲裁與保守決策,Critic 對策略包做反例、成本、資安與資料邊界審查。 | `no_send_strategy_review_ready` |
+
+## Agent 工作狀態
+
+| Agent | 專業責任 | 工作量 | 產出 | 下一步 |
+|---|---|---:|---|---|
+| MarketRadar | AI 技術市場來源監控、版本 freshness、release / docs 變更分類 | `47` | 20 項技術 / 47 sources / 0 failures 的雷達 readback | 維持每 6 小時只讀監控,變更進日報與週報 scorecard。 |
+| Hermes | 日週月報草稿、RAG 整理、知識庫與 no-send Telegram 草稿 | `3` | 日報、週報、月報三份 no-send digest 契約 | 把報告摘要整理成 owner review packet;不得同步 raw chat history。 |
+| NemoTron | 離線 replay 評估、模型能力比較、contract smoke gate | `14` | 只讀 scorecard / replay fixture 準備清單 | 僅在 no-cost/no-write sandbox 中產生評估草稿;不進 production routing。 |
+| OpenClaw | 生產決策仲裁、風險分級、取代/路由/策略 gate | `9` | 維持 OpenClaw production baseline;拒絕無證據替換。 | 等待 replay / shadow / canary 與 owner approval 後才可做高風險決策。 |
+| Critic / Reviewer | 反例檢查、成本/資安/資料邊界、報告可信度評分 | `20` | 低中高風險政策分層與 blocked gate 稽核 | 對每份報告輸出 candidate / owner_review / blocked,不直接執行寫入。 |
+
+## 報告後 AI 分析包
+
+| 報告 | 風險 | 發現 | 解法 | 執行邊界 |
+|---|---|---|---|---|
+| daily | `low` | 0 個來源失敗,0 個技術變更。 | 維持只讀監控;若來源失敗大於 0,自動建立 report-source-gap 草案與 no-send Telegram 摘要。 | 可產生草稿與文件提案;不得 live send、不得改 workflow、不得打外部付費 API。 |
+| weekly | `medium` | 14 個高優先級技術需要週期性 scorecard。 | 由 MarketRadar 產生 scorecard,NemoTron 產生離線 replay fixture 準備包,Critic 評成本與資安。 | 可準備 sandbox / replay 設計包;不得安裝 SDK、不得啟動 replay runner、不得切路由。 |
+| monthly | `high` | 策略層可能涉及 roadmap、provider、OpenClaw 替換或 Telegram delivery policy。 | 只輸出 owner review package;通過 replay / shadow / canary 與成本/資料邊界審核後才可執行。 | 高風險全部禁止自動寫入;必須人工批准後另開 execution gate。 |
+
+## 風險分層自動化政策
+
+| 風險 | Agent 可自動做 | 禁止 | 回報 |
+|---|---|---|---|
+| `low` | 來源分類、摘要、no-send 草稿、文件與 snapshot 提案。 | 不得 live send、不得寫 production、不得呼叫付費 API。 | 自動進日報,並在前端顯示處理建議。 |
+| `medium` | scorecard、sandbox 設計、replay fixture 準備包與 owner review draft。 | 不得安裝 SDK、不得新增 MCP server、不得觸發 workflow 或路由切換。 | 進週報與 Telegram no-send 草稿,等待 owner review。 |
+| `high` | 只允許風險分析、反例檢查與人工審核包。 | 不得自動執行任何 runtime / host / provider / OpenClaw 替換動作。 | 進月報與高風險 owner review,不做自動處理。 |
+
+## 仍被 Gate 擋下
+
+- `telegram_send_enabled=false`
+- `bot_api_call_enabled=false`
+- `report_receipt_write_enabled=false`
+- `ai_post_report_analysis_live_run_enabled=false`
+- `low_medium_runtime_auto_write_enabled=false`
+- `high_risk_owner_review_required=true`
+- `sdk_installation_approved=false`
+- `paid_api_calls_approved=false`
+- `production_routing_approved=false`
+- `model_provider_switch_approved=false`
+- `host_write_approved=false`
+- `openclaw_replacement_approved=false`
diff --git a/docs/operations/AI-TECHNOLOGY-REPORT-CADENCE-READBACK.md b/docs/operations/AI-TECHNOLOGY-REPORT-CADENCE-READBACK.md
new file mode 100644
index 00000000..926b663f
--- /dev/null
+++ b/docs/operations/AI-TECHNOLOGY-REPORT-CADENCE-READBACK.md
@@ -0,0 +1,63 @@
+# AI 技術雷達日報 / 週報 / 月報讀回
+
+- 產生時間:`2026-06-25T06:13:58.765962+00:00`
+- 整體治理完成度:`42.2%`
+- 報告節奏完成度:`100.0%`
+- 報告節奏:`3/3`
+- 圖表區塊:`6`
+- Agent 工作狀態報告:`5`
+- 報告後 AI 分析包:`3`
+- 低中風險自動化提案:`6`
+- 高風險 owner review:`5`
+- Telegram live send:`False`
+- 正式送出 / receipt / auto optimization 寫入:`0` / `0` / `0`
+- 狀態:`daily_weekly_monthly_reports_ready_no_send_gated`
+
+## 報告節奏
+
+| 節奏 | Owner Agent | 內容 | AI 看完後做什麼 | Telegram |
+|---|---|---|---|---|
+| 日報 | Hermes | 彙整 6 小時雷達輸出、來源失敗、版本變更、審核佇列與低中風險處理建議。 | Hermes 先摘要,MarketRadar 標示 freshness,Critic 檢查是否可低風險自動處理。 | `no_send_draft_ready` |
+| 週報 | MarketRadar | 刷新技術 scorecard,判斷 sandbox、offline replay、adapter design 與 watchlist 優先級。 | NemoTron 只做離線 replay / scorecard 草稿,OpenClaw 只讀審核分數並維持 policy guard。 | `no_send_scorecard_ready` |
+| 月報 | OpenClaw | 彙整市場趨勢,提出 roadmap / watch-only / retire / replacement-review 策略包。 | OpenClaw 只做仲裁與保守決策,Critic 對策略包做反例、成本、資安與資料邊界審查。 | `no_send_strategy_review_ready` |
+
+## Agent 工作狀態
+
+| Agent | 專業責任 | 工作量 | 產出 | 下一步 |
+|---|---|---:|---|---|
+| MarketRadar | AI 技術市場來源監控、版本 freshness、release / docs 變更分類 | `47` | 20 項技術 / 47 sources / 0 failures 的雷達 readback | 維持每 6 小時只讀監控,變更進日報與週報 scorecard。 |
+| Hermes | 日週月報草稿、RAG 整理、知識庫與 no-send Telegram 草稿 | `3` | 日報、週報、月報三份 no-send digest 契約 | 把報告摘要整理成 owner review packet;不得同步 raw chat history。 |
+| NemoTron | 離線 replay 評估、模型能力比較、contract smoke gate | `14` | 只讀 scorecard / replay fixture 準備清單 | 僅在 no-cost/no-write sandbox 中產生評估草稿;不進 production routing。 |
+| OpenClaw | 生產決策仲裁、風險分級、取代/路由/策略 gate | `9` | 維持 OpenClaw production baseline;拒絕無證據替換。 | 等待 replay / shadow / canary 與 owner approval 後才可做高風險決策。 |
+| Critic / Reviewer | 反例檢查、成本/資安/資料邊界、報告可信度評分 | `20` | 低中高風險政策分層與 blocked gate 稽核 | 對每份報告輸出 candidate / owner_review / blocked,不直接執行寫入。 |
+
+## 報告後 AI 分析包
+
+| 報告 | 風險 | 發現 | 解法 | 執行邊界 |
+|---|---|---|---|---|
+| daily | `low` | 0 個來源失敗,0 個技術變更。 | 維持只讀監控;若來源失敗大於 0,自動建立 report-source-gap 草案與 no-send Telegram 摘要。 | 可產生草稿與文件提案;不得 live send、不得改 workflow、不得打外部付費 API。 |
+| weekly | `medium` | 14 個高優先級技術需要週期性 scorecard。 | 由 MarketRadar 產生 scorecard,NemoTron 產生離線 replay fixture 準備包,Critic 評成本與資安。 | 可準備 sandbox / replay 設計包;不得安裝 SDK、不得啟動 replay runner、不得切路由。 |
+| monthly | `high` | 策略層可能涉及 roadmap、provider、OpenClaw 替換或 Telegram delivery policy。 | 只輸出 owner review package;通過 replay / shadow / canary 與成本/資料邊界審核後才可執行。 | 高風險全部禁止自動寫入;必須人工批准後另開 execution gate。 |
+
+## 風險分層自動化政策
+
+| 風險 | Agent 可自動做 | 禁止 | 回報 |
+|---|---|---|---|
+| `low` | 來源分類、摘要、no-send 草稿、文件與 snapshot 提案。 | 不得 live send、不得寫 production、不得呼叫付費 API。 | 自動進日報,並在前端顯示處理建議。 |
+| `medium` | scorecard、sandbox 設計、replay fixture 準備包與 owner review draft。 | 不得安裝 SDK、不得新增 MCP server、不得觸發 workflow 或路由切換。 | 進週報與 Telegram no-send 草稿,等待 owner review。 |
+| `high` | 只允許風險分析、反例檢查與人工審核包。 | 不得自動執行任何 runtime / host / provider / OpenClaw 替換動作。 | 進月報與高風險 owner review,不做自動處理。 |
+
+## 仍被 Gate 擋下
+
+- `telegram_send_enabled=false`
+- `bot_api_call_enabled=false`
+- `report_receipt_write_enabled=false`
+- `ai_post_report_analysis_live_run_enabled=false`
+- `low_medium_runtime_auto_write_enabled=false`
+- `high_risk_owner_review_required=true`
+- `sdk_installation_approved=false`
+- `paid_api_calls_approved=false`
+- `production_routing_approved=false`
+- `model_provider_switch_approved=false`
+- `host_write_approved=false`
+- `openclaw_replacement_approved=false`
diff --git a/docs/operations/ai-technology-report-cadence-readback.snapshot.json b/docs/operations/ai-technology-report-cadence-readback.snapshot.json
new file mode 100644
index 00000000..20fa6d04
--- /dev/null
+++ b/docs/operations/ai-technology-report-cadence-readback.snapshot.json
@@ -0,0 +1,353 @@
+{
+ "agent_workload_reports": [
+ {
+ "agent": "MarketRadar",
+ "latest_output": "20 項技術 / 47 sources / 0 failures 的雷達 readback",
+ "next_action": "維持每 6 小時只讀監控,變更進日報與週報 scorecard。",
+ "professional_responsibility": "AI 技術市場來源監控、版本 freshness、release / docs 變更分類",
+ "work_unit_count": 47,
+ "work_unit_label": "primary source checks"
+ },
+ {
+ "agent": "Hermes",
+ "latest_output": "日報、週報、月報三份 no-send digest 契約",
+ "next_action": "把報告摘要整理成 owner review packet;不得同步 raw chat history。",
+ "professional_responsibility": "日週月報草稿、RAG 整理、知識庫與 no-send Telegram 草稿",
+ "work_unit_count": 3,
+ "work_unit_label": "report cadences"
+ },
+ {
+ "agent": "NemoTron",
+ "latest_output": "只讀 scorecard / replay fixture 準備清單",
+ "next_action": "僅在 no-cost/no-write sandbox 中產生評估草稿;不進 production routing。",
+ "professional_responsibility": "離線 replay 評估、模型能力比較、contract smoke gate",
+ "work_unit_count": 14,
+ "work_unit_label": "high-priority review candidates"
+ },
+ {
+ "agent": "OpenClaw",
+ "latest_output": "維持 OpenClaw production baseline;拒絕無證據替換。",
+ "next_action": "等待 replay / shadow / canary 與 owner approval 後才可做高風險決策。",
+ "professional_responsibility": "生產決策仲裁、風險分級、取代/路由/策略 gate",
+ "work_unit_count": 9,
+ "work_unit_label": "policy gates guarded"
+ },
+ {
+ "agent": "Critic / Reviewer",
+ "latest_output": "低中高風險政策分層與 blocked gate 稽核",
+ "next_action": "對每份報告輸出 candidate / owner_review / blocked,不直接執行寫入。",
+ "professional_responsibility": "反例檢查、成本/資安/資料邊界、報告可信度評分",
+ "work_unit_count": 20,
+ "work_unit_label": "technology fit checks"
+ }
+ ],
+ "blocked_gates": [
+ "telegram_send_enabled=false",
+ "bot_api_call_enabled=false",
+ "report_receipt_write_enabled=false",
+ "ai_post_report_analysis_live_run_enabled=false",
+ "low_medium_runtime_auto_write_enabled=false",
+ "high_risk_owner_review_required=true",
+ "sdk_installation_approved=false",
+ "paid_api_calls_approved=false",
+ "production_routing_approved=false",
+ "model_provider_switch_approved=false",
+ "host_write_approved=false",
+ "openclaw_replacement_approved=false"
+ ],
+ "chart_sections": [
+ {
+ "chart_id": "source_health_kpi",
+ "chart_type": "metric_strip",
+ "expected_report_signal": "來源失敗大於 0 時進日報與 owner review queue。",
+ "primary_metric": "source_failures",
+ "title": "來源健康 KPI",
+ "value": 0
+ },
+ {
+ "chart_id": "technology_domain_bar",
+ "chart_type": "bar",
+ "expected_report_signal": "每個領域至少要能回溯代表技術、優先級與 changed count。",
+ "primary_metric": "technology_domains",
+ "title": "技術領域覆蓋圖",
+ "value": 6
+ },
+ {
+ "chart_id": "agent_workload_stack",
+ "chart_type": "stacked_bar",
+ "expected_report_signal": "每個 Agent 必須有工作量、產出與下一步。",
+ "primary_metric": "work_unit_count",
+ "title": "Agent 工作量堆疊圖",
+ "value": 5
+ },
+ {
+ "chart_id": "risk_action_matrix",
+ "chart_type": "matrix",
+ "expected_report_signal": "低中風險可產生提案,高風險必須 owner review。",
+ "primary_metric": "risk_tiers",
+ "title": "風險處置矩陣",
+ "value": 3
+ },
+ {
+ "chart_id": "telegram_delivery_gate",
+ "chart_type": "gate_cards",
+ "expected_report_signal": "no-send 草稿可見,但 live send / receipt write 保持 false。",
+ "primary_metric": "telegram_send_enabled",
+ "title": "Telegram 送出 Gate",
+ "value": 0
+ },
+ {
+ "chart_id": "post_report_analysis_flow",
+ "chart_type": "flow",
+ "expected_report_signal": "每份報告都要產生 finding、solution、risk tier 與 execution boundary。",
+ "primary_metric": "post_report_analysis_packets",
+ "title": "報告後 AI 分析流程",
+ "value": 3
+ }
+ ],
+ "forbidden_actions_without_new_approval": [
+ "直接發送 Telegram live report",
+ "寫入 report receipt 或 owner acceptance event bus",
+ "執行低中風險 runtime write、host write、K8s write 或 workflow trigger",
+ "安裝 SDK / MCP server / package",
+ "切換模型 provider、生產路由或 OpenClaw 決策核心"
+ ],
+ "generated_at": "2026-06-25T06:13:58.765962+00:00",
+ "next_allowed_actions": [
+ "顯示日報、週報、月報 readback 與圖表化摘要",
+ "產生 no-send Telegram 草稿與 owner review packet",
+ "讓 Hermes / MarketRadar / Critic 讀取 committed reports 後輸出建議",
+ "把低中風險項目先轉成文件、scorecard 或 sandbox 提案"
+ ],
+ "policy": {
+ "ai_post_report_analysis_live_run_enabled": false,
+ "bot_api_call_enabled": false,
+ "high_risk_owner_review_required": true,
+ "host_write_approved": false,
+ "low_medium_runtime_auto_write_enabled": false,
+ "model_provider_switch_approved": false,
+ "openclaw_replacement_approved": false,
+ "paid_api_calls_approved": false,
+ "production_routing_approved": false,
+ "raw_chat_history_synced": false,
+ "raw_report_payload_display_allowed": false,
+ "read_only": true,
+ "report_delivery_enabled": false,
+ "report_receipt_write_enabled": false,
+ "sdk_installation_approved": false,
+ "telegram_send_enabled": false
+ },
+ "post_report_analysis_packets": [
+ {
+ "agent_decision": "agent_auto_propose_no_write",
+ "execution_boundary": "可產生草稿與文件提案;不得 live send、不得改 workflow、不得打外部付費 API。",
+ "key_finding": "0 個來源失敗,0 個技術變更。",
+ "proposed_solution": "維持只讀監控;若來源失敗大於 0,自動建立 report-source-gap 草案與 no-send Telegram 摘要。",
+ "report_id": "daily",
+ "risk_tier": "low"
+ },
+ {
+ "agent_decision": "agent_auto_prepare_owner_packet",
+ "execution_boundary": "可準備 sandbox / replay 設計包;不得安裝 SDK、不得啟動 replay runner、不得切路由。",
+ "key_finding": "14 個高優先級技術需要週期性 scorecard。",
+ "proposed_solution": "由 MarketRadar 產生 scorecard,NemoTron 產生離線 replay fixture 準備包,Critic 評成本與資安。",
+ "report_id": "weekly",
+ "risk_tier": "medium"
+ },
+ {
+ "agent_decision": "owner_review_required",
+ "execution_boundary": "高風險全部禁止自動寫入;必須人工批准後另開 execution gate。",
+ "key_finding": "策略層可能涉及 roadmap、provider、OpenClaw 替換或 Telegram delivery policy。",
+ "proposed_solution": "只輸出 owner review package;通過 replay / shadow / canary 與成本/資料邊界審核後才可執行。",
+ "report_id": "monthly",
+ "risk_tier": "high"
+ }
+ ],
+ "report_cadences": [
+ {
+ "ai_analysis_after_reading": "Hermes 先摘要,MarketRadar 標示 freshness,Critic 檢查是否可低風險自動處理。",
+ "cadence": "daily",
+ "cadence_label": "日報",
+ "chart_types": [
+ "來源成功率 KPI",
+ "技術領域柱狀圖",
+ "審核佇列狀態列"
+ ],
+ "data_inputs": [
+ "ai_technology_radar_readback.summary",
+ "technology_domains",
+ "high_priority_review_queue",
+ "rolling_update_controls"
+ ],
+ "high_risk_owner_review_actions": [
+ "SDK / API / provider / Telegram / host write 全部送 owner review"
+ ],
+ "low_medium_auto_actions": [
+ "建立 no-send report-source-gap 提案",
+ "更新 watch-only 分類建議"
+ ],
+ "metrics": {
+ "changed_technologies": 0,
+ "source_count": 47,
+ "source_failures": 0,
+ "technology_count": 20
+ },
+ "owner_agent": "Hermes",
+ "report_purpose": "彙整 6 小時雷達輸出、來源失敗、版本變更、審核佇列與低中風險處理建議。",
+ "reviewer_agent": "MarketRadar",
+ "telegram_delivery_status": "no_send_draft_ready"
+ },
+ {
+ "ai_analysis_after_reading": "NemoTron 只做離線 replay / scorecard 草稿,OpenClaw 只讀審核分數並維持 policy guard。",
+ "cadence": "weekly",
+ "cadence_label": "週報",
+ "chart_types": [
+ "候選技術矩陣",
+ "Agent 工作量堆疊圖",
+ "風險 gate 熱點圖"
+ ],
+ "data_inputs": [
+ "integration_candidates",
+ "professional_agent_roles",
+ "blocked_gates",
+ "source_scope"
+ ],
+ "high_risk_owner_review_actions": [
+ "進 shadow/canary、production routing 或 OpenClaw 替換 ADR 前必須 owner approval"
+ ],
+ "low_medium_auto_actions": [
+ "產生 sandbox / adapter design 草案",
+ "更新 replay fixture 準備清單"
+ ],
+ "metrics": {
+ "blocked_gate_count": 9,
+ "high_priority_count": 14,
+ "integration_candidate_count": 20,
+ "review_queue_count": 0
+ },
+ "owner_agent": "MarketRadar",
+ "report_purpose": "刷新技術 scorecard,判斷 sandbox、offline replay、adapter design 與 watchlist 優先級。",
+ "reviewer_agent": "NemoTron",
+ "telegram_delivery_status": "no_send_scorecard_ready"
+ },
+ {
+ "ai_analysis_after_reading": "OpenClaw 只做仲裁與保守決策,Critic 對策略包做反例、成本、資安與資料邊界審查。",
+ "cadence": "monthly",
+ "cadence_label": "月報",
+ "chart_types": [
+ "Roadmap 決策漏斗",
+ "Watch-only 保留/淘汰矩陣",
+ "高風險審核包狀態圖"
+ ],
+ "data_inputs": [
+ "technology_area_counts",
+ "rolling_update_controls",
+ "risk_automation_policy",
+ "telegram_report_bridge"
+ ],
+ "high_risk_owner_review_actions": [
+ "OpenClaw 替換、provider 切換、付費 API 與 Telegram live delivery 都維持 owner review"
+ ],
+ "low_medium_auto_actions": [
+ "整理 roadmap candidate 文件草案",
+ "標記 watch-only 技術保留原因"
+ ],
+ "metrics": {
+ "high_priority_count": 14,
+ "openclaw_replacement_approved": 0,
+ "policy_hold_count": 9,
+ "technology_area_count": 6
+ },
+ "owner_agent": "OpenClaw",
+ "report_purpose": "彙整市場趨勢,提出 roadmap / watch-only / retire / replacement-review 策略包。",
+ "reviewer_agent": "Critic / Reviewer",
+ "telegram_delivery_status": "no_send_strategy_review_ready"
+ }
+ ],
+ "report_contract": {
+ "api_endpoint": "/api/v1/agents/ai-technology-report-cadence-readback",
+ "daily": "每日顯示來源失敗、版本變更、審核佇列、低中風險建議與 Telegram no-send 草稿。",
+ "frontend_target": "/zh-TW/governance?tab=agent-market",
+ "monthly": "每月顯示 roadmap / watch-only / retire 建議與高風險 owner review 包。",
+ "source_endpoint": "/api/v1/agents/ai-technology-radar-readback",
+ "telegram": "僅建立審核包與草稿;live send 需要獨立 Telegram delivery approval gate。",
+ "weekly": "每週顯示技術 scorecard、Agent 工作量、sandbox / replay / adapter design 優先級。"
+ },
+ "risk_automation_policy": [
+ {
+ "agent_auto_scope": "來源分類、摘要、no-send 草稿、文件與 snapshot 提案。",
+ "blocked_without_approval": "不得 live send、不得寫 production、不得呼叫付費 API。",
+ "reporting_mode": "自動進日報,並在前端顯示處理建議。",
+ "risk_tier": "low"
+ },
+ {
+ "agent_auto_scope": "scorecard、sandbox 設計、replay fixture 準備包與 owner review draft。",
+ "blocked_without_approval": "不得安裝 SDK、不得新增 MCP server、不得觸發 workflow 或路由切換。",
+ "reporting_mode": "進週報與 Telegram no-send 草稿,等待 owner review。",
+ "risk_tier": "medium"
+ },
+ {
+ "agent_auto_scope": "只允許風險分析、反例檢查與人工審核包。",
+ "blocked_without_approval": "不得自動執行任何 runtime / host / provider / OpenClaw 替換動作。",
+ "reporting_mode": "進月報與高風險 owner review,不做自動處理。",
+ "risk_tier": "high"
+ }
+ ],
+ "schema_version": "ai_technology_report_cadence_readback_v1",
+ "source_scope": {
+ "frontend_target": "/zh-TW/governance?tab=agent-market",
+ "gitea_main_evidence_basis_commit": "5dbe2870",
+ "radar_readback": "docs/operations/ai-technology-radar-readback.snapshot.json",
+ "scope_note": "本讀回只整合已提交的 AI 技術雷達、日週月報契約與治理 gate;不包含 raw chat history、secret、session 或本機工作視窗內容。",
+ "technology_watch_report": "docs/evaluations/ai_technology_watch_report_2026-06-25.json"
+ },
+ "summary": {
+ "agent_status_report_count": 5,
+ "auto_optimization_write_count": 0,
+ "chart_section_count": 6,
+ "high_risk_owner_review_count": 5,
+ "live_delivery_count_24h": 0,
+ "low_medium_auto_action_proposal_count": 6,
+ "overall_completion_percent": 42.2,
+ "policy_hold_count": 17,
+ "post_report_analysis_packet_count": 3,
+ "report_cadence_completion_percent": 100.0,
+ "report_cadence_count": 3,
+ "report_ready_count": 3,
+ "report_receipt_write_count_24h": 0,
+ "source_count": 47,
+ "source_failures": 0,
+ "status": "daily_weekly_monthly_reports_ready_no_send_gated",
+ "technology_count": 20,
+ "telegram_send_enabled": false
+ },
+ "telegram_report_bridge": {
+ "bot_api_call_enabled": false,
+ "canonical_group_env": "SRE_GROUP_CHAT_ID",
+ "delivery_note": "目前只產生 Telegram Bot 送出前的審核包與 no-send 草稿;沒有呼叫 Bot API,也沒有寫入 receipt。",
+ "draft_count": 3,
+ "drafts": [
+ {
+ "cadence": "daily",
+ "draft_id": "ai_technology_daily_digest",
+ "required_gate": "telegram_send_approved=true",
+ "status": "no_send_draft_ready"
+ },
+ {
+ "cadence": "weekly",
+ "draft_id": "ai_technology_weekly_scorecard",
+ "required_gate": "telegram_send_approved=true",
+ "status": "no_send_draft_ready"
+ },
+ {
+ "cadence": "monthly",
+ "draft_id": "ai_technology_monthly_strategy_review",
+ "required_gate": "telegram_send_approved=true",
+ "status": "no_send_draft_ready"
+ }
+ ],
+ "integration_status": "approval_package_ready_no_live_send",
+ "report_receipt_write_enabled": false,
+ "telegram_send_enabled": false
+ }
+}
diff --git a/docs/schemas/ai_technology_report_cadence_readback_v1.schema.json b/docs/schemas/ai_technology_report_cadence_readback_v1.schema.json
new file mode 100644
index 00000000..af8e6e6c
--- /dev/null
+++ b/docs/schemas/ai_technology_report_cadence_readback_v1.schema.json
@@ -0,0 +1,178 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "urn:awoooi:ai-technology-report-cadence-readback-v1",
+ "title": "AWOOOI AI 技術雷達日週月報讀回快照 (v1)",
+ "type": "object",
+ "required": [
+ "schema_version",
+ "generated_at",
+ "source_scope",
+ "summary",
+ "policy",
+ "report_cadences",
+ "agent_workload_reports",
+ "chart_sections",
+ "post_report_analysis_packets",
+ "risk_automation_policy",
+ "telegram_report_bridge",
+ "blocked_gates",
+ "next_allowed_actions",
+ "forbidden_actions_without_new_approval",
+ "report_contract"
+ ],
+ "properties": {
+ "schema_version": {
+ "type": "string",
+ "const": "ai_technology_report_cadence_readback_v1"
+ },
+ "generated_at": {
+ "type": "string",
+ "minLength": 1
+ },
+ "source_scope": {
+ "type": "object",
+ "additionalProperties": true
+ },
+ "summary": {
+ "type": "object",
+ "required": [
+ "overall_completion_percent",
+ "report_cadence_completion_percent",
+ "report_cadence_count",
+ "report_ready_count",
+ "chart_section_count",
+ "agent_status_report_count",
+ "post_report_analysis_packet_count",
+ "low_medium_auto_action_proposal_count",
+ "high_risk_owner_review_count",
+ "technology_count",
+ "source_count",
+ "source_failures",
+ "telegram_send_enabled",
+ "live_delivery_count_24h",
+ "report_receipt_write_count_24h",
+ "auto_optimization_write_count",
+ "policy_hold_count",
+ "status"
+ ],
+ "properties": {
+ "overall_completion_percent": {"type": "number"},
+ "report_cadence_completion_percent": {"type": "number"},
+ "report_cadence_count": {"type": "integer", "minimum": 0},
+ "report_ready_count": {"type": "integer", "minimum": 0},
+ "chart_section_count": {"type": "integer", "minimum": 0},
+ "agent_status_report_count": {"type": "integer", "minimum": 0},
+ "post_report_analysis_packet_count": {"type": "integer", "minimum": 0},
+ "low_medium_auto_action_proposal_count": {"type": "integer", "minimum": 0},
+ "high_risk_owner_review_count": {"type": "integer", "minimum": 0},
+ "technology_count": {"type": "integer", "minimum": 0},
+ "source_count": {"type": "integer", "minimum": 0},
+ "source_failures": {"type": "integer", "minimum": 0},
+ "telegram_send_enabled": {"type": "boolean", "const": false},
+ "live_delivery_count_24h": {"type": "integer", "const": 0},
+ "report_receipt_write_count_24h": {"type": "integer", "const": 0},
+ "auto_optimization_write_count": {"type": "integer", "const": 0},
+ "policy_hold_count": {"type": "integer", "minimum": 0},
+ "status": {"type": "string", "minLength": 1}
+ },
+ "additionalProperties": true
+ },
+ "policy": {
+ "type": "object",
+ "required": [
+ "read_only",
+ "raw_chat_history_synced",
+ "raw_report_payload_display_allowed",
+ "report_delivery_enabled",
+ "telegram_send_enabled",
+ "bot_api_call_enabled",
+ "report_receipt_write_enabled",
+ "ai_post_report_analysis_live_run_enabled",
+ "low_medium_runtime_auto_write_enabled",
+ "high_risk_owner_review_required",
+ "sdk_installation_approved",
+ "paid_api_calls_approved",
+ "production_routing_approved",
+ "model_provider_switch_approved",
+ "host_write_approved",
+ "openclaw_replacement_approved"
+ ],
+ "properties": {
+ "read_only": {"type": "boolean", "const": true},
+ "raw_chat_history_synced": {"type": "boolean", "const": false},
+ "raw_report_payload_display_allowed": {"type": "boolean", "const": false},
+ "report_delivery_enabled": {"type": "boolean", "const": false},
+ "telegram_send_enabled": {"type": "boolean", "const": false},
+ "bot_api_call_enabled": {"type": "boolean", "const": false},
+ "report_receipt_write_enabled": {"type": "boolean", "const": false},
+ "ai_post_report_analysis_live_run_enabled": {"type": "boolean", "const": false},
+ "low_medium_runtime_auto_write_enabled": {"type": "boolean", "const": false},
+ "high_risk_owner_review_required": {"type": "boolean", "const": true},
+ "sdk_installation_approved": {"type": "boolean", "const": false},
+ "paid_api_calls_approved": {"type": "boolean", "const": false},
+ "production_routing_approved": {"type": "boolean", "const": false},
+ "model_provider_switch_approved": {"type": "boolean", "const": false},
+ "host_write_approved": {"type": "boolean", "const": false},
+ "openclaw_replacement_approved": {"type": "boolean", "const": false}
+ },
+ "additionalProperties": true
+ },
+ "report_cadences": {
+ "type": "array",
+ "items": {"type": "object", "additionalProperties": true}
+ },
+ "agent_workload_reports": {
+ "type": "array",
+ "items": {"type": "object", "additionalProperties": true}
+ },
+ "chart_sections": {
+ "type": "array",
+ "items": {"type": "object", "additionalProperties": true}
+ },
+ "post_report_analysis_packets": {
+ "type": "array",
+ "items": {"type": "object", "additionalProperties": true}
+ },
+ "risk_automation_policy": {
+ "type": "array",
+ "items": {"type": "object", "additionalProperties": true}
+ },
+ "telegram_report_bridge": {
+ "type": "object",
+ "required": [
+ "integration_status",
+ "telegram_send_enabled",
+ "bot_api_call_enabled",
+ "report_receipt_write_enabled",
+ "draft_count",
+ "drafts"
+ ],
+ "properties": {
+ "integration_status": {"type": "string", "minLength": 1},
+ "telegram_send_enabled": {"type": "boolean", "const": false},
+ "bot_api_call_enabled": {"type": "boolean", "const": false},
+ "report_receipt_write_enabled": {"type": "boolean", "const": false},
+ "draft_count": {"type": "integer", "minimum": 0},
+ "drafts": {"type": "array"}
+ },
+ "additionalProperties": true
+ },
+ "blocked_gates": {
+ "type": "array",
+ "items": {"type": "string", "minLength": 1}
+ },
+ "next_allowed_actions": {
+ "type": "array",
+ "items": {"type": "string", "minLength": 1}
+ },
+ "forbidden_actions_without_new_approval": {
+ "type": "array",
+ "items": {"type": "string", "minLength": 1}
+ },
+ "report_contract": {
+ "type": "object",
+ "additionalProperties": true
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/scripts/dev/ai-technology-report-cadence-readback.py b/scripts/dev/ai-technology-report-cadence-readback.py
new file mode 100644
index 00000000..acc079d3
--- /dev/null
+++ b/scripts/dev/ai-technology-report-cadence-readback.py
@@ -0,0 +1,542 @@
+#!/usr/bin/env python3
+"""Build the AWOOOI AI technology report cadence 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_report_cadence(
+ *,
+ radar_readback: dict[str, Any],
+ evidence_commit: str,
+ generated_at: str | None = None,
+) -> dict[str, Any]:
+ """Build daily / weekly / monthly AI technology report readback."""
+ _require_schema(radar_readback, "ai_technology_radar_readback_v1", "radar_readback")
+ summary = radar_readback.get("summary") or {}
+ policy = radar_readback.get("policy") or {}
+ source_count = int(summary.get("source_count", 0))
+ technology_count = int(summary.get("technology_count", 0))
+ high_priority_count = int(summary.get("high_priority_count", 0))
+ source_failures = int(summary.get("source_failures", 0))
+ blocked_gates = list(radar_readback.get("blocked_gates") or [])
+ policy_holds = [
+ key
+ for key, value in policy.items()
+ if key != "read_only" and value is False
+ ]
+
+ report_cadences = _report_cadences(radar_readback)
+ agent_workload_reports = _agent_workload_reports(
+ source_count=source_count,
+ technology_count=technology_count,
+ high_priority_count=high_priority_count,
+ blocked_gate_count=len(blocked_gates),
+ )
+ post_report_packets = _post_report_analysis_packets(radar_readback)
+
+ return {
+ "schema_version": "ai_technology_report_cadence_readback_v1",
+ "generated_at": generated_at or datetime.now(timezone.utc).isoformat(),
+ "source_scope": {
+ "radar_readback": "docs/operations/ai-technology-radar-readback.snapshot.json",
+ "technology_watch_report": radar_readback["source_scope"]["technology_watch_report"],
+ "frontend_target": "/zh-TW/governance?tab=agent-market",
+ "gitea_main_evidence_basis_commit": evidence_commit,
+ "scope_note": "本讀回只整合已提交的 AI 技術雷達、日週月報契約與治理 gate;不包含 raw chat history、secret、session 或本機工作視窗內容。",
+ },
+ "summary": {
+ "overall_completion_percent": float(summary.get("overall_completion_percent", 42.2)),
+ "report_cadence_completion_percent": 100.0,
+ "report_cadence_count": len(report_cadences),
+ "report_ready_count": len(report_cadences),
+ "chart_section_count": 6,
+ "agent_status_report_count": len(agent_workload_reports),
+ "post_report_analysis_packet_count": len(post_report_packets),
+ "low_medium_auto_action_proposal_count": 6,
+ "high_risk_owner_review_count": 5,
+ "technology_count": technology_count,
+ "source_count": source_count,
+ "source_failures": source_failures,
+ "telegram_send_enabled": False,
+ "live_delivery_count_24h": 0,
+ "report_receipt_write_count_24h": 0,
+ "auto_optimization_write_count": 0,
+ "policy_hold_count": len(policy_holds) + len(blocked_gates),
+ "status": "daily_weekly_monthly_reports_ready_no_send_gated",
+ },
+ "policy": {
+ "read_only": True,
+ "raw_chat_history_synced": False,
+ "raw_report_payload_display_allowed": False,
+ "report_delivery_enabled": False,
+ "telegram_send_enabled": False,
+ "bot_api_call_enabled": False,
+ "report_receipt_write_enabled": False,
+ "ai_post_report_analysis_live_run_enabled": False,
+ "low_medium_runtime_auto_write_enabled": False,
+ "high_risk_owner_review_required": True,
+ "sdk_installation_approved": False,
+ "paid_api_calls_approved": False,
+ "production_routing_approved": False,
+ "model_provider_switch_approved": False,
+ "host_write_approved": False,
+ "openclaw_replacement_approved": False,
+ },
+ "report_cadences": report_cadences,
+ "agent_workload_reports": agent_workload_reports,
+ "chart_sections": _chart_sections(radar_readback),
+ "post_report_analysis_packets": post_report_packets,
+ "risk_automation_policy": _risk_automation_policy(),
+ "telegram_report_bridge": {
+ "integration_status": "approval_package_ready_no_live_send",
+ "canonical_group_env": "SRE_GROUP_CHAT_ID",
+ "telegram_send_enabled": False,
+ "bot_api_call_enabled": False,
+ "report_receipt_write_enabled": False,
+ "draft_count": 3,
+ "drafts": [
+ {
+ "draft_id": "ai_technology_daily_digest",
+ "cadence": "daily",
+ "status": "no_send_draft_ready",
+ "required_gate": "telegram_send_approved=true",
+ },
+ {
+ "draft_id": "ai_technology_weekly_scorecard",
+ "cadence": "weekly",
+ "status": "no_send_draft_ready",
+ "required_gate": "telegram_send_approved=true",
+ },
+ {
+ "draft_id": "ai_technology_monthly_strategy_review",
+ "cadence": "monthly",
+ "status": "no_send_draft_ready",
+ "required_gate": "telegram_send_approved=true",
+ },
+ ],
+ "delivery_note": "目前只產生 Telegram Bot 送出前的審核包與 no-send 草稿;沒有呼叫 Bot API,也沒有寫入 receipt。",
+ },
+ "blocked_gates": [
+ "telegram_send_enabled=false",
+ "bot_api_call_enabled=false",
+ "report_receipt_write_enabled=false",
+ "ai_post_report_analysis_live_run_enabled=false",
+ "low_medium_runtime_auto_write_enabled=false",
+ "high_risk_owner_review_required=true",
+ "sdk_installation_approved=false",
+ "paid_api_calls_approved=false",
+ "production_routing_approved=false",
+ "model_provider_switch_approved=false",
+ "host_write_approved=false",
+ "openclaw_replacement_approved=false",
+ ],
+ "next_allowed_actions": [
+ "顯示日報、週報、月報 readback 與圖表化摘要",
+ "產生 no-send Telegram 草稿與 owner review packet",
+ "讓 Hermes / MarketRadar / Critic 讀取 committed reports 後輸出建議",
+ "把低中風險項目先轉成文件、scorecard 或 sandbox 提案",
+ ],
+ "forbidden_actions_without_new_approval": [
+ "直接發送 Telegram live report",
+ "寫入 report receipt 或 owner acceptance event bus",
+ "執行低中風險 runtime write、host write、K8s write 或 workflow trigger",
+ "安裝 SDK / MCP server / package",
+ "切換模型 provider、生產路由或 OpenClaw 決策核心",
+ ],
+ "report_contract": {
+ "api_endpoint": "/api/v1/agents/ai-technology-report-cadence-readback",
+ "frontend_target": "/zh-TW/governance?tab=agent-market",
+ "source_endpoint": "/api/v1/agents/ai-technology-radar-readback",
+ "daily": "每日顯示來源失敗、版本變更、審核佇列、低中風險建議與 Telegram no-send 草稿。",
+ "weekly": "每週顯示技術 scorecard、Agent 工作量、sandbox / replay / adapter design 優先級。",
+ "monthly": "每月顯示 roadmap / watch-only / retire 建議與高風險 owner review 包。",
+ "telegram": "僅建立審核包與草稿;live send 需要獨立 Telegram delivery approval gate。",
+ },
+ }
+
+
+def render_markdown(payload: dict[str, Any]) -> str:
+ """Render a Traditional Chinese operator report."""
+ summary = payload["summary"]
+ lines = [
+ "# AI 技術雷達日報 / 週報 / 月報讀回",
+ "",
+ f"- 產生時間:`{payload['generated_at']}`",
+ f"- 整體治理完成度:`{summary['overall_completion_percent']}%`",
+ f"- 報告節奏完成度:`{summary['report_cadence_completion_percent']}%`",
+ f"- 報告節奏:`{summary['report_ready_count']}/{summary['report_cadence_count']}`",
+ f"- 圖表區塊:`{summary['chart_section_count']}`",
+ f"- Agent 工作狀態報告:`{summary['agent_status_report_count']}`",
+ f"- 報告後 AI 分析包:`{summary['post_report_analysis_packet_count']}`",
+ f"- 低中風險自動化提案:`{summary['low_medium_auto_action_proposal_count']}`",
+ f"- 高風險 owner review:`{summary['high_risk_owner_review_count']}`",
+ f"- Telegram live send:`{summary['telegram_send_enabled']}`",
+ f"- 正式送出 / receipt / auto optimization 寫入:`{summary['live_delivery_count_24h']}` / `{summary['report_receipt_write_count_24h']}` / `{summary['auto_optimization_write_count']}`",
+ f"- 狀態:`{summary['status']}`",
+ "",
+ "## 報告節奏",
+ "",
+ "| 節奏 | Owner Agent | 內容 | AI 看完後做什麼 | Telegram |",
+ "|---|---|---|---|---|",
+ ]
+ for cadence in payload["report_cadences"]:
+ lines.append(
+ f"| {cadence['cadence_label']} | {cadence['owner_agent']} | "
+ f"{cadence['report_purpose']} | {cadence['ai_analysis_after_reading']} | "
+ f"`{cadence['telegram_delivery_status']}` |"
+ )
+
+ lines.extend([
+ "",
+ "## Agent 工作狀態",
+ "",
+ "| Agent | 專業責任 | 工作量 | 產出 | 下一步 |",
+ "|---|---|---:|---|---|",
+ ])
+ for row in payload["agent_workload_reports"]:
+ lines.append(
+ f"| {row['agent']} | {row['professional_responsibility']} | "
+ f"`{row['work_unit_count']}` | {row['latest_output']} | {row['next_action']} |"
+ )
+
+ lines.extend([
+ "",
+ "## 報告後 AI 分析包",
+ "",
+ "| 報告 | 風險 | 發現 | 解法 | 執行邊界 |",
+ "|---|---|---|---|---|",
+ ])
+ for packet in payload["post_report_analysis_packets"]:
+ lines.append(
+ f"| {packet['report_id']} | `{packet['risk_tier']}` | "
+ f"{packet['key_finding']} | {packet['proposed_solution']} | {packet['execution_boundary']} |"
+ )
+
+ lines.extend([
+ "",
+ "## 風險分層自動化政策",
+ "",
+ "| 風險 | Agent 可自動做 | 禁止 | 回報 |",
+ "|---|---|---|---|",
+ ])
+ for row in payload["risk_automation_policy"]:
+ lines.append(
+ f"| `{row['risk_tier']}` | {row['agent_auto_scope']} | "
+ f"{row['blocked_without_approval']} | {row['reporting_mode']} |"
+ )
+
+ lines.extend([
+ "",
+ "## 仍被 Gate 擋下",
+ "",
+ ])
+ for gate in payload["blocked_gates"]:
+ lines.append(f"- `{gate}`")
+ lines.append("")
+ return "\n".join(lines)
+
+
+def _report_cadences(radar: dict[str, Any]) -> list[dict[str, Any]]:
+ summary = radar["summary"]
+ return [
+ {
+ "cadence": "daily",
+ "cadence_label": "日報",
+ "owner_agent": "Hermes",
+ "reviewer_agent": "MarketRadar",
+ "report_purpose": "彙整 6 小時雷達輸出、來源失敗、版本變更、審核佇列與低中風險處理建議。",
+ "data_inputs": [
+ "ai_technology_radar_readback.summary",
+ "technology_domains",
+ "high_priority_review_queue",
+ "rolling_update_controls",
+ ],
+ "metrics": {
+ "technology_count": int(summary.get("technology_count", 0)),
+ "source_count": int(summary.get("source_count", 0)),
+ "source_failures": int(summary.get("source_failures", 0)),
+ "changed_technologies": int(summary.get("changed_technologies", 0)),
+ },
+ "chart_types": ["來源成功率 KPI", "技術領域柱狀圖", "審核佇列狀態列"],
+ "ai_analysis_after_reading": "Hermes 先摘要,MarketRadar 標示 freshness,Critic 檢查是否可低風險自動處理。",
+ "low_medium_auto_actions": [
+ "建立 no-send report-source-gap 提案",
+ "更新 watch-only 分類建議",
+ ],
+ "high_risk_owner_review_actions": [
+ "SDK / API / provider / Telegram / host write 全部送 owner review",
+ ],
+ "telegram_delivery_status": "no_send_draft_ready",
+ },
+ {
+ "cadence": "weekly",
+ "cadence_label": "週報",
+ "owner_agent": "MarketRadar",
+ "reviewer_agent": "NemoTron",
+ "report_purpose": "刷新技術 scorecard,判斷 sandbox、offline replay、adapter design 與 watchlist 優先級。",
+ "data_inputs": [
+ "integration_candidates",
+ "professional_agent_roles",
+ "blocked_gates",
+ "source_scope",
+ ],
+ "metrics": {
+ "integration_candidate_count": len(radar.get("integration_candidates") or []),
+ "high_priority_count": int(summary.get("high_priority_count", 0)),
+ "review_queue_count": int(summary.get("review_queue_count", 0)),
+ "blocked_gate_count": len(radar.get("blocked_gates") or []),
+ },
+ "chart_types": ["候選技術矩陣", "Agent 工作量堆疊圖", "風險 gate 熱點圖"],
+ "ai_analysis_after_reading": "NemoTron 只做離線 replay / scorecard 草稿,OpenClaw 只讀審核分數並維持 policy guard。",
+ "low_medium_auto_actions": [
+ "產生 sandbox / adapter design 草案",
+ "更新 replay fixture 準備清單",
+ ],
+ "high_risk_owner_review_actions": [
+ "進 shadow/canary、production routing 或 OpenClaw 替換 ADR 前必須 owner approval",
+ ],
+ "telegram_delivery_status": "no_send_scorecard_ready",
+ },
+ {
+ "cadence": "monthly",
+ "cadence_label": "月報",
+ "owner_agent": "OpenClaw",
+ "reviewer_agent": "Critic / Reviewer",
+ "report_purpose": "彙整市場趨勢,提出 roadmap / watch-only / retire / replacement-review 策略包。",
+ "data_inputs": [
+ "technology_area_counts",
+ "rolling_update_controls",
+ "risk_automation_policy",
+ "telegram_report_bridge",
+ ],
+ "metrics": {
+ "technology_area_count": int(summary.get("technology_area_count", 0)),
+ "high_priority_count": int(summary.get("high_priority_count", 0)),
+ "policy_hold_count": len(radar.get("blocked_gates") or []),
+ "openclaw_replacement_approved": 0,
+ },
+ "chart_types": ["Roadmap 決策漏斗", "Watch-only 保留/淘汰矩陣", "高風險審核包狀態圖"],
+ "ai_analysis_after_reading": "OpenClaw 只做仲裁與保守決策,Critic 對策略包做反例、成本、資安與資料邊界審查。",
+ "low_medium_auto_actions": [
+ "整理 roadmap candidate 文件草案",
+ "標記 watch-only 技術保留原因",
+ ],
+ "high_risk_owner_review_actions": [
+ "OpenClaw 替換、provider 切換、付費 API 與 Telegram live delivery 都維持 owner review",
+ ],
+ "telegram_delivery_status": "no_send_strategy_review_ready",
+ },
+ ]
+
+
+def _agent_workload_reports(
+ *,
+ source_count: int,
+ technology_count: int,
+ high_priority_count: int,
+ blocked_gate_count: int,
+) -> list[dict[str, Any]]:
+ return [
+ {
+ "agent": "MarketRadar",
+ "professional_responsibility": "AI 技術市場來源監控、版本 freshness、release / docs 變更分類",
+ "work_unit_count": source_count,
+ "work_unit_label": "primary source checks",
+ "latest_output": "20 項技術 / 47 sources / 0 failures 的雷達 readback",
+ "next_action": "維持每 6 小時只讀監控,變更進日報與週報 scorecard。",
+ },
+ {
+ "agent": "Hermes",
+ "professional_responsibility": "日週月報草稿、RAG 整理、知識庫與 no-send Telegram 草稿",
+ "work_unit_count": 3,
+ "work_unit_label": "report cadences",
+ "latest_output": "日報、週報、月報三份 no-send digest 契約",
+ "next_action": "把報告摘要整理成 owner review packet;不得同步 raw chat history。",
+ },
+ {
+ "agent": "NemoTron",
+ "professional_responsibility": "離線 replay 評估、模型能力比較、contract smoke gate",
+ "work_unit_count": high_priority_count,
+ "work_unit_label": "high-priority review candidates",
+ "latest_output": "只讀 scorecard / replay fixture 準備清單",
+ "next_action": "僅在 no-cost/no-write sandbox 中產生評估草稿;不進 production routing。",
+ },
+ {
+ "agent": "OpenClaw",
+ "professional_responsibility": "生產決策仲裁、風險分級、取代/路由/策略 gate",
+ "work_unit_count": blocked_gate_count,
+ "work_unit_label": "policy gates guarded",
+ "latest_output": "維持 OpenClaw production baseline;拒絕無證據替換。",
+ "next_action": "等待 replay / shadow / canary 與 owner approval 後才可做高風險決策。",
+ },
+ {
+ "agent": "Critic / Reviewer",
+ "professional_responsibility": "反例檢查、成本/資安/資料邊界、報告可信度評分",
+ "work_unit_count": technology_count,
+ "work_unit_label": "technology fit checks",
+ "latest_output": "低中高風險政策分層與 blocked gate 稽核",
+ "next_action": "對每份報告輸出 candidate / owner_review / blocked,不直接執行寫入。",
+ },
+ ]
+
+
+def _chart_sections(radar: dict[str, Any]) -> list[dict[str, Any]]:
+ summary = radar["summary"]
+ return [
+ {
+ "chart_id": "source_health_kpi",
+ "title": "來源健康 KPI",
+ "chart_type": "metric_strip",
+ "primary_metric": "source_failures",
+ "value": int(summary.get("source_failures", 0)),
+ "expected_report_signal": "來源失敗大於 0 時進日報與 owner review queue。",
+ },
+ {
+ "chart_id": "technology_domain_bar",
+ "title": "技術領域覆蓋圖",
+ "chart_type": "bar",
+ "primary_metric": "technology_domains",
+ "value": len(radar.get("technology_domains") or []),
+ "expected_report_signal": "每個領域至少要能回溯代表技術、優先級與 changed count。",
+ },
+ {
+ "chart_id": "agent_workload_stack",
+ "title": "Agent 工作量堆疊圖",
+ "chart_type": "stacked_bar",
+ "primary_metric": "work_unit_count",
+ "value": 5,
+ "expected_report_signal": "每個 Agent 必須有工作量、產出與下一步。",
+ },
+ {
+ "chart_id": "risk_action_matrix",
+ "title": "風險處置矩陣",
+ "chart_type": "matrix",
+ "primary_metric": "risk_tiers",
+ "value": 3,
+ "expected_report_signal": "低中風險可產生提案,高風險必須 owner review。",
+ },
+ {
+ "chart_id": "telegram_delivery_gate",
+ "title": "Telegram 送出 Gate",
+ "chart_type": "gate_cards",
+ "primary_metric": "telegram_send_enabled",
+ "value": 0,
+ "expected_report_signal": "no-send 草稿可見,但 live send / receipt write 保持 false。",
+ },
+ {
+ "chart_id": "post_report_analysis_flow",
+ "title": "報告後 AI 分析流程",
+ "chart_type": "flow",
+ "primary_metric": "post_report_analysis_packets",
+ "value": 3,
+ "expected_report_signal": "每份報告都要產生 finding、solution、risk tier 與 execution boundary。",
+ },
+ ]
+
+
+def _post_report_analysis_packets(radar: dict[str, Any]) -> list[dict[str, Any]]:
+ summary = radar["summary"]
+ return [
+ {
+ "report_id": "daily",
+ "risk_tier": "low",
+ "key_finding": f"{summary.get('source_failures', 0)} 個來源失敗,{summary.get('changed_technologies', 0)} 個技術變更。",
+ "proposed_solution": "維持只讀監控;若來源失敗大於 0,自動建立 report-source-gap 草案與 no-send Telegram 摘要。",
+ "agent_decision": "agent_auto_propose_no_write",
+ "execution_boundary": "可產生草稿與文件提案;不得 live send、不得改 workflow、不得打外部付費 API。",
+ },
+ {
+ "report_id": "weekly",
+ "risk_tier": "medium",
+ "key_finding": f"{summary.get('high_priority_count', 0)} 個高優先級技術需要週期性 scorecard。",
+ "proposed_solution": "由 MarketRadar 產生 scorecard,NemoTron 產生離線 replay fixture 準備包,Critic 評成本與資安。",
+ "agent_decision": "agent_auto_prepare_owner_packet",
+ "execution_boundary": "可準備 sandbox / replay 設計包;不得安裝 SDK、不得啟動 replay runner、不得切路由。",
+ },
+ {
+ "report_id": "monthly",
+ "risk_tier": "high",
+ "key_finding": "策略層可能涉及 roadmap、provider、OpenClaw 替換或 Telegram delivery policy。",
+ "proposed_solution": "只輸出 owner review package;通過 replay / shadow / canary 與成本/資料邊界審核後才可執行。",
+ "agent_decision": "owner_review_required",
+ "execution_boundary": "高風險全部禁止自動寫入;必須人工批准後另開 execution gate。",
+ },
+ ]
+
+
+def _risk_automation_policy() -> list[dict[str, Any]]:
+ return [
+ {
+ "risk_tier": "low",
+ "agent_auto_scope": "來源分類、摘要、no-send 草稿、文件與 snapshot 提案。",
+ "blocked_without_approval": "不得 live send、不得寫 production、不得呼叫付費 API。",
+ "reporting_mode": "自動進日報,並在前端顯示處理建議。",
+ },
+ {
+ "risk_tier": "medium",
+ "agent_auto_scope": "scorecard、sandbox 設計、replay fixture 準備包與 owner review draft。",
+ "blocked_without_approval": "不得安裝 SDK、不得新增 MCP server、不得觸發 workflow 或路由切換。",
+ "reporting_mode": "進週報與 Telegram no-send 草稿,等待 owner review。",
+ },
+ {
+ "risk_tier": "high",
+ "agent_auto_scope": "只允許風險分析、反例檢查與人工審核包。",
+ "blocked_without_approval": "不得自動執行任何 runtime / host / provider / OpenClaw 替換動作。",
+ "reporting_mode": "進月報與高風險 owner review,不做自動處理。",
+ },
+ ]
+
+
+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 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 technology report cadence readback.")
+ parser.add_argument("--radar-readback", required=True)
+ parser.add_argument("--evidence-commit", required=True)
+ parser.add_argument("--output", required=True)
+ parser.add_argument("--markdown-output", required=True)
+ parser.add_argument("--markdown-alias-output")
+ args = parser.parse_args()
+
+ payload = build_report_cadence(
+ radar_readback=load_json(Path(args.radar_readback)),
+ evidence_commit=args.evidence_commit,
+ )
+ 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")
+ if args.markdown_alias_output:
+ Path(args.markdown_alias_output).write_text(markdown, encoding="utf-8")
+ print(
+ "AI_TECHNOLOGY_REPORT_CADENCE_READBACK_OK "
+ f"overall={payload['summary']['overall_completion_percent']}% "
+ f"reports={payload['summary']['report_ready_count']}/{payload['summary']['report_cadence_count']} "
+ f"charts={payload['summary']['chart_section_count']} "
+ f"agents={payload['summary']['agent_status_report_count']} "
+ f"telegram_send={payload['summary']['telegram_send_enabled']}"
+ )
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())