feat(governance): 顯性化 AI Agent 日週月報主看板
Some checks failed
Code Review / ai-code-review (push) Successful in 13s
CD Pipeline / tests (push) Successful in 1m39s
CD Pipeline / build-and-deploy (push) Failing after 30m25s
CD Pipeline / post-deploy-checks (push) Has been skipped

This commit is contained in:
Your Name
2026-06-16 11:44:21 +08:00
parent bb459d59f9
commit 9f4ed2854e
5 changed files with 246 additions and 1 deletions

View File

@@ -4291,6 +4291,26 @@
"reportStatusBoard": {
"title": "P2-108 日週月報與 Agent 工作狀態總覽",
"source": "{generated} · {current} → {next}",
"heroTitle": "日報 / 週報 / 月報",
"heroSubtitle": "{current} 已完成 {percent}%;下一關 {next} 只處理 runtime 啟動前驗證。",
"heroStatusLine": "三份報告本體已在治理頁可見:日報、週報、月報皆為只讀草案;目前不排程、不寫 Gateway queue、不實發 Telegram、不啟動 AI 自動優化。",
"heroCadenceVisible": "日報 {daily} · 週報 {weekly} · 月報 {monthly}",
"heroAgentTitle": "每個 AI Agent 工作狀態",
"heroChartTitle": "數據化圖表",
"heroMetrics": {
"visibleReports": "報告可見",
"workload": "工作量完成",
"waitingApproval": "待審核",
"liveTelegram": "live Telegram",
"liveOptimization": "live 優化"
},
"heroLabels": {
"reportProgress": "報告完成度",
"reportDetail": "章節 {sections};圖表 {charts};工作量 {work}live {live}",
"nextGate": "下一關:{gate}",
"agentWorkload": "工作量完成",
"agentDetail": "{done}/{total} 已完成;{approval} 待審核24h live {live}"
},
"truthTitle": "報告完成狀態",
"boundaryTitle": "live 啟用邊界",
"metrics": {

View File

@@ -4291,6 +4291,26 @@
"reportStatusBoard": {
"title": "P2-108 日週月報與 Agent 工作狀態總覽",
"source": "{generated} · {current} → {next}",
"heroTitle": "日報 / 週報 / 月報",
"heroSubtitle": "{current} 已完成 {percent}%;下一關 {next} 只處理 runtime 啟動前驗證。",
"heroStatusLine": "三份報告本體已在治理頁可見:日報、週報、月報皆為只讀草案;目前不排程、不寫 Gateway queue、不實發 Telegram、不啟動 AI 自動優化。",
"heroCadenceVisible": "日報 {daily} · 週報 {weekly} · 月報 {monthly}",
"heroAgentTitle": "每個 AI Agent 工作狀態",
"heroChartTitle": "數據化圖表",
"heroMetrics": {
"visibleReports": "報告可見",
"workload": "工作量完成",
"waitingApproval": "待審核",
"liveTelegram": "live Telegram",
"liveOptimization": "live 優化"
},
"heroLabels": {
"reportProgress": "報告完成度",
"reportDetail": "章節 {sections};圖表 {charts};工作量 {work}live {live}",
"nextGate": "下一關:{gate}",
"agentWorkload": "工作量完成",
"agentDetail": "{done}/{total} 已完成;{approval} 待審核24h live {live}"
},
"truthTitle": "報告完成狀態",
"boundaryTitle": "live 啟用邊界",
"metrics": {

View File

@@ -4000,6 +4000,184 @@ export function AutomationInventoryTab() {
]}
/>
<GlassCard variant="subtle" padding="md">
<div style={{ display: 'flex', flexDirection: 'column', gap: 14, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, minWidth: 0 }}>
<div style={{
width: 38,
height: 38,
borderRadius: 8,
border: '0.5px solid #4f46e540',
background: 'rgba(79,70,229,0.08)',
color: '#4f46e5',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
}}>
<FileText size={18} />
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 5, minWidth: 0 }}>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 18, fontWeight: 700, color: '#141413', lineHeight: 1.15, overflowWrap: 'anywhere' }}>
{t('reportStatusBoard.heroTitle')}
</span>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 11, color: '#5c5a55', lineHeight: 1.55, overflowWrap: 'anywhere' }}>
{t('reportStatusBoard.heroSubtitle', {
current: reportStatusBoard.program_status.current_task_id,
percent: reportStatusOverall,
next: reportStatusBoard.program_status.next_task_id,
})}
</span>
</div>
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-end', gap: 6, minWidth: 0 }}>
<Chip value={t('reportStatusBoard.source', {
generated: formatDateTime(reportStatusBoard.generated_at),
current: reportStatusBoard.program_status.current_task_id,
next: reportStatusBoard.program_status.next_task_id,
})} muted />
<Chip value={t('reportStatusBoard.heroCadenceVisible', {
daily: String(reportStatusBoard.report_completion_truth.daily_report_visible),
weekly: String(reportStatusBoard.report_completion_truth.weekly_report_visible),
monthly: String(reportStatusBoard.report_completion_truth.monthly_report_visible),
})} />
</div>
</div>
<div style={{ padding: 11, border: '0.5px solid #dde3ff', borderRadius: 7, background: '#f8faff', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 11, color: '#4f5565', lineHeight: 1.55, overflowWrap: 'anywhere' }}>
{t('reportStatusBoard.heroStatusLine')}
</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
<Chip value={t('reportStatusBoard.flags.send', { value: String(reportStatusBoard.activation_boundaries.telegram_send_enabled) })} muted />
<Chip value={t('reportStatusBoard.flags.queue', { value: String(reportStatusBoard.activation_boundaries.gateway_queue_write_enabled) })} muted />
<Chip value={t('reportStatusBoard.flags.analysis', { value: String(reportStatusBoard.activation_boundaries.ai_analysis_run_enabled) })} muted />
<Chip value={t('reportStatusBoard.flags.optimization', { value: String(reportStatusBoard.activation_boundaries.production_optimization_write_enabled) })} muted />
<Chip value={t('reportStatusBoard.flags.highApproval', { value: String(reportStatusBoard.activation_boundaries.high_risk_requires_human_approval) })} />
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(148px, 1fr))', gap: 10 }} className="automation-inventory-live-read-kpi-grid">
<div style={{ padding: 11, border: '0.5px solid #dde3ff', borderRadius: 7, background: '#fff', minWidth: 0 }}>
<SmallLabel>{t('reportStatusBoard.heroMetrics.visibleReports')}</SmallLabel>
<div style={{ marginTop: 6, fontFamily: 'Syne, sans-serif', fontSize: 25, fontWeight: 700, color: '#22C55E', lineHeight: 1 }}>
{reportStatusBoard.rollups.completed_report_count}/{reportStatusCards}
</div>
</div>
<div style={{ padding: 11, border: '0.5px solid #dde3ff', borderRadius: 7, background: '#fff', minWidth: 0 }}>
<SmallLabel>{t('reportStatusBoard.heroMetrics.workload')}</SmallLabel>
<div style={{ marginTop: 6, fontFamily: 'Syne, sans-serif', fontSize: 25, fontWeight: 700, color: '#141413', lineHeight: 1 }}>
{reportStatusDone}/{reportStatusWorkload}
</div>
</div>
<div style={{ padding: 11, border: '0.5px solid #dde3ff', borderRadius: 7, background: '#fff', minWidth: 0 }}>
<SmallLabel>{t('reportStatusBoard.heroMetrics.waitingApproval')}</SmallLabel>
<div style={{ marginTop: 6, fontFamily: 'Syne, sans-serif', fontSize: 25, fontWeight: 700, color: reportStatusWaitingApproval > 0 ? '#F59E0B' : '#22C55E', lineHeight: 1 }}>
{reportStatusWaitingApproval}
</div>
</div>
<div style={{ padding: 11, border: '0.5px solid #dde3ff', borderRadius: 7, background: '#fff', minWidth: 0 }}>
<SmallLabel>{t('reportStatusBoard.heroMetrics.liveTelegram')}</SmallLabel>
<div style={{ marginTop: 6, fontFamily: 'Syne, sans-serif', fontSize: 25, fontWeight: 700, color: reportStatusBoard.rollups.live_telegram_send_count === 0 ? '#22C55E' : '#EF4444', lineHeight: 1 }}>
{reportStatusBoard.rollups.live_telegram_send_count}
</div>
</div>
<div style={{ padding: 11, border: '0.5px solid #dde3ff', borderRadius: 7, background: '#fff', minWidth: 0 }}>
<SmallLabel>{t('reportStatusBoard.heroMetrics.liveOptimization')}</SmallLabel>
<div style={{ marginTop: 6, fontFamily: 'Syne, sans-serif', fontSize: 25, fontWeight: 700, color: reportStatusLiveOptimization === 0 ? '#22C55E' : '#EF4444', lineHeight: 1 }}>
{reportStatusLiveOptimization}
</div>
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 10 }} className="automation-inventory-live-read-card-grid">
{reportStatusBoard.report_status_cards.map(card => (
<div key={`hero-${card.cadence_id}`} style={{ padding: 12, border: '0.5px solid #c7d2fe', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 9, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, minWidth: 0 }}>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 15, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
{card.display_name}
</span>
<Chip value={redisDryRunValueLabel('agents', card.owner_agent)} muted />
</div>
<MiniBar
label={t('reportStatusBoard.heroLabels.reportProgress')}
value={card.completion_percent}
detail={t('reportStatusBoard.heroLabels.reportDetail', {
sections: card.sections_count,
charts: card.chart_count,
work: card.work_units_total,
live: card.live_delivery_count,
})}
tone="ok"
/>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
<Chip value={card.contract_state} muted />
<Chip value={card.delivery_state} muted />
</div>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#62636b', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
{t('reportStatusBoard.heroLabels.nextGate', { gate: card.next_gate })}
</span>
</div>
))}
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.1fr) minmax(0, 0.9fr)', gap: 10 }} className="automation-inventory-live-read-grid">
<div style={{ padding: 12, border: '0.5px solid #dde3ff', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 9, minWidth: 0 }}>
<SmallLabel>{t('reportStatusBoard.heroAgentTitle')}</SmallLabel>
{reportStatusBoard.agent_status_reports.map(agent => {
const progress = agent.work_units_total > 0 ? Math.round((agent.work_units_done / agent.work_units_total) * 100) : 0
return (
<div key={`hero-agent-${agent.agent_id}`} style={{ display: 'grid', gridTemplateColumns: '104px minmax(0, 1fr)', gap: 9, alignItems: 'center', minWidth: 0 }}>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
{agent.display_name}
</span>
<MiniBar
label={t('reportStatusBoard.heroLabels.agentWorkload')}
value={progress}
detail={t('reportStatusBoard.heroLabels.agentDetail', {
done: agent.work_units_done,
total: agent.work_units_total,
approval: agent.work_units_waiting_approval,
live: agent.live_runtime_work_units_24h,
})}
tone={progress >= 85 ? 'ok' : 'warn'}
/>
</div>
)
})}
</div>
<div style={{ padding: 12, border: '0.5px solid #dde3ff', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 9, minWidth: 0 }}>
<SmallLabel>{t('reportStatusBoard.heroChartTitle')}</SmallLabel>
{visibleReportStatusCharts.map(chart => {
const maxValue = Math.max(...chart.series.map(item => item.value), 1)
return (
<div key={`hero-chart-${chart.chart_id}`} style={{ display: 'flex', flexDirection: 'column', gap: 6, minWidth: 0 }}>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
{chart.display_name}
</span>
{chart.series.map(item => (
<div key={`hero-chart-${chart.chart_id}-${item.label}`} style={{ display: 'grid', gridTemplateColumns: '76px minmax(0, 1fr) 36px', gap: 8, alignItems: 'center', minWidth: 0 }}>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#605f59', overflowWrap: 'anywhere' }}>
{item.label}
</span>
<div style={{ height: 7, borderRadius: 999, background: '#e7e3d8', overflow: 'hidden' }}>
<div style={{ height: '100%', width: `${Math.max(4, Math.round((item.value / maxValue) * 100))}%`, borderRadius: 999, background: toneColor(item.tone) }} />
</div>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, fontWeight: 700, color: toneColor(item.tone), textAlign: 'right' }}>
{item.value}
</span>
</div>
))}
</div>
)
})}
</div>
</div>
</div>
</GlassCard>
<GlassCard variant="subtle" padding="md">
<div style={{ display: 'flex', flexDirection: 'column', gap: 13, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>

View File

@@ -1,3 +1,30 @@
## 2026-06-16P2-405E AI Agent 日週月報主看板顯性化
**背景**:統帥明確指出在 governance automation inventory 頁面仍「看不到日報、週報、月報」。既有 `ai_agent_report_status_board_v1`、API 與中段 UI 已能證明日報 / 週報 / 月報 `3/3` 可見,但入口被埋在長頁面中,視覺權重不足。本階段只做前端顯性化與文件同步,不新增發送、批准、排程或寫入能力。
**完成項目**
- Governance automation inventory 頁在 `AgentActivityConstellation` 後新增「日報 / 週報 / 月報」主看板。
- 主看板直接顯示 `AI Agent 日報``AI Agent 週報``AI Agent 月報` 三張報告卡,完成度皆取自既有 committed snapshot維持 `100%`
- 主看板新增第一眼 KPI報告可見 `3/3`、工作量完成 `79/91`、待審核 `12`、live Telegram `0`、live 優化 `0`
- 主看板新增每個 AI Agent 工作狀態摘要OpenClaw、Hermes、NemoTron 的完成 / 總工作量、待審核與 24h live runtime work units。
- 主看板新增數據化圖表區:日週月報完成度、每個 Agent 工作量與 runtime 啟用邊界,保留既有完整 P2-108 明細區塊。
- UI 文案新增 `reportStatusBoard.hero*` 鍵;`zh-TW``en` locale 皆使用繁體中文,避免報告入口被 P2 編號遮住。
**邊界**
- 本階段不排程、不寫 Gateway queue、不呼叫 Bot API、不實發 Telegram、不啟動 AI analysis worker、不啟動中低風險自動優化、不寫 production。
- 高風險仍需人工審核;中低風險自動處理仍需後續 runtime gate 與 receipt / verifier evidence。
- 前端仍遵守遮罩合約,不顯示工作視窗對話、內部協作逐字稿、未核准推理、未遮罩載荷或機密明文。
**驗證狀態**
- `python3 -m json.tool apps/web/messages/zh-TW.json``apps/web/messages/en.json` 通過。
- `git diff --check` 通過。
- 本輪新增前端 diff 精準掃描未命中 `批准!`、工作視窗、逐字稿、`source_thread_id`、未遮罩 payload、機密明文或 `blocked_waiting_`
- `pnpm --filter @awoooi/web typecheck` 通過。
- `python3 scripts/ops/doc-secrets-sanity-check.py docs .gitea apps/web/messages/zh-TW.json apps/web/messages/en.json 'apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx'``DOC_SECRET_SANITY_OK scanned_files=890`
- `python3 scripts/security/security-mirror-progress-guard.py --root .``SECURITY_MIRROR_PROGRESS_GUARD_OK`
- 首次未帶 `NEXT_PUBLIC_API_URL` 的本地 production build 依前端禁令 fatal重跑 `NEXT_PUBLIC_API_URL=https://awoooi.wooo.work NEXT_PRIVATE_BUILD_WORKER_COUNT=1 SENTRY_SUPPRESS_GLOBAL_ERROR_HANDLER_FILE_WARNING=1 pnpm --filter @awoooi/web build` 通過static pages `92/92``/zh-TW/governance` First Load JS `454 kB`
- Gitea / CD 與 Production 驗證待本輪後續補記。
## 2026-06-16Monitoring / Alerting / Observability 事故後回讀 Gate
**背景**110 冷啟動、端口異動、Prometheus / Alertmanager / StockPlatform / Harbor / registry / Ollama route 類事故證明,監控告警不能只看 dashboard up、route `200`、CD success、訊息預覽或 UI 可見。IwoooS 必須補上監控告警事故後回讀欄位確認告警規則、datasource、scrape target、receiver route、silence / mute / dedup / inhibit、通知回執、dashboard / trace / log freshness、reload / no-reload、rollback 與跨專案同步;本階段只建立 readback plan、snapshot、guard 與前台 marker不 reload Prometheus / Alertmanager、不改 Grafana / SigNoz / Sentry / Langfuse / OTEL、不發 Telegram、不 fire live alert、不做 alert-chain smoke、不 SSH、不做 host write。

View File

@@ -1192,7 +1192,7 @@ UI
| P2-105 | 完成 | 100 | OpenClaw + Hermes + NemoTron | 批准前加入 critic / reviewer 評分 | `ai_agent_critic_reviewer_result_capture_v1` / snapshot / 只讀 API / governance UI5 張 Agent scorecard、5 個 result capture contract、6 個 promotion gate、4 條 candidate routeapproved gap `63`、failed candidate `1`runtime score / result capture write / learning / trust / queue / Telegram 全為 `0` | 已由 P2-106 承接;不寫 score、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram |
| P2-106 | 完成 | 100 | OpenClaw + Hermes + NemoTron | owner-approved result capture dry-run | `ai_agent_owner_approved_result_capture_dry_run_v1` / schema / snapshot / 只讀 API / governance UI5 個 no-write result capture template、5 個 score fixture、7 個 dry-run gate、5 個 operator actionowner approval received、preview generated、score / result capture / learning / trust / queue / Telegram 全部 `0` | 已由 P2-107 承接;不啟動 live write、不送 Telegram、不更新 PlayBook trust |
| P2-107 | 完成 | 100 | OpenClaw + Hermes + NemoTron | owner-approved result capture readback / promotion readiness | `ai_agent_owner_approved_result_capture_readback_v1` / schema / snapshot / 只讀 API / governance UI正式站 deploy marker `834ccdba` 已驗證5 個 readback digest、5 個 promotion review、4 條 failure lane、4 個 reviewer queue preview、5 個 operator actionowner approval received、readback generated、promotion approved、reviewer queue write、score / result capture / learning / trust / queue / Telegram 全部 `0` | 已由 P2-108 承接;不讀 canonical runtime target、不寫 reviewer queue、不啟動 live writer |
| P2-108 | 完成 | 100 | Hermes + OpenClaw + NemoTron | 日週月報與 Agent 工作狀態總覽 | `ai_agent_report_status_board_v1` / schema / snapshot / 只讀 API / governance UI日報 / 週報 / 月報可見完成度皆 `100%`Agent 狀態 `3`、圖表 `3`、統帥問答卡 `4`scheduler / Gateway queue / Telegram / AI analysis / auto optimization 全部 `0` | 已由 P2-109 承接;不排程、不送 Telegram、不啟動 AI runtime |
| P2-108 | 完成 | 100 | Hermes + OpenClaw + NemoTron | 日週月報與 Agent 工作狀態總覽 | `ai_agent_report_status_board_v1` / schema / snapshot / 只讀 API / governance UI日報 / 週報 / 月報可見完成度皆 `100%`Agent 狀態 `3`、圖表 `3`、統帥問答卡 `4`2026-06-16 已追加前段「日報 / 週報 / 月報」主看板,直接顯示報告 `3/3`、工作量 `79/91`、待審核 `12`、live Telegram `0`、live 優化 `0`scheduler / Gateway queue / Telegram / AI analysis / auto optimization 全部 `0` | 已由 P2-109 承接;不排程、不送 Telegram、不啟動 AI runtime |
| P2-109 | 完成 | 100 | OpenClaw + Hermes + NemoTron | runtime readback approval package | `ai_agent_runtime_readback_approval_package_v1` / schema / snapshot / 只讀 API / governance UI5 個批准包、4 個 canonical readback plan、4 條 rollback drill、4 個 Telegram failure receipt gate、5 個 operator actionruntime readback / queue / send / write 全為 `0` | 已由 P2-110 承接;不讀 canonical runtime target、不寫 reviewer queue、不送 Telegram |
| P2-110 | 完成 | 100 | OpenClaw + Hermes + NemoTron | runtime readback implementation review | `ai_agent_runtime_readback_implementation_review_v1` / schema / snapshot / 只讀 API / governance UI5 張 implementation review card、5 個 no-write verifier、5 個 blocker、5 個 operator actionlive query / runtime execution / production write 全為 `0` | 已由 P2-111 承接;不啟動 live query、不寫 Gateway queue |
| P2-111 | 完成 | 100 | Hermes + OpenClaw + NemoTron | report live delivery approval package | `ai_agent_report_live_delivery_approval_package_v1` / schema / snapshot / 只讀 API / governance UI5 個實發批准包、4 個 route lock gate、5 個 payload redaction check、4 個 no-send receipt、5 個 operator actionscheduler / Gateway queue / Telegram / Bot API / report receipt / AI analysis 全為 `0` | 已由 P2-112 承接;不排程、不實發、不寫回執 |