Files
ewoooc/docs/guides/observability_ui_governance.md
OoO 07c9e200d0
Some checks failed
CD Pipeline / deploy (push) Failing after 1m39s
test(observability): add UI regression guard
2026-05-05 15:04:21 +08:00

69 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI 觀測台 UI Governance
> Scope: `/observability/*` pages using `ewoooc_base.html` and `.momo-observability-mode`.
## 目標
AI 觀測台是「AI 中樞控制室」,不是 Bootstrap 報表頁。任何新增或修改都必須維持暖色焦糖系、Noto Sans TC、點陣方格、卡片化資料面、可降級空狀態。
## 必守規範
- 使用 `static/css/observability-system.css` 的 token 與 utility class。
- 標題使用 `--obs-title-size`KPI 數字使用 `--obs-value-size`
- 圖表容器使用 `.obs-chart-frame``.obs-chart-frame-tall``.obs-chart-frame-slim`
- 頁面資料缺表或 migration 未完成時,顯示安全空狀態,不得把 SQL exception 顯示給使用者。
- 側欄必須維持暖深咖啡背景,第二/三層文字要有足夠對比。
- 表格必須有暖色表頭、row hover、長文字換行保護。
- 手機與中螢幕要能自動從多欄收成單欄。
## 禁止事項
- 不要在 template 裡新增 Times / Georgia / serif 作為主標題字型。
- 不要新增紫色系、純黑 sidebar、純白卡片 hover。
- 不要把整頁做成寬表格;資料密集內容優先用卡片、矩陣、可橫向 overflow 的表格。
- 不要硬寫超大 `font-size: clamp(...)`;先調 token。
- 不要新增 `style="height:..."` 圖表容器;使用 chart frame class。
- 不要用 `查詢失敗: ProgrammingError...` 顯示給使用者。
## 新頁 checklist
1. Template 設定正確 `active_page`,讓 `observability-system.css` 載入。
2. Hero 有清楚頁面任務,不做簡報封面式大字。
3. 第一屏有 3 到 6 個可行動 KPI不堆原始資料。
4. 主資料區先呈現結論,再給明細。
5. 空資料、缺表、外部服務未接入都要是可讀狀態。
6. 10 頁巡檢不得出現 `Traceback``UndefinedError``ProgrammingError``relation "``查詢失敗:`
## 驗收指令
### 1. Repo 靜態 UI guard
先跑本地 guard避免把已知 UI/UX 回歸重新帶進 repo
```bash
python3 scripts/check_observability_ui.py
```
Guard 會檢查:
- Times / Georgia 等非規範標題字型。
- SQL/Jinja exception 文案外露。
- 圖表 `style="height:..."` 與靜態 `style="width:..."`
- 過大標題 clamp 與純白 hover/card surface。
- 觀測台 CSS 必要 token / utility class 是否仍存在。
### 2. Production 10 頁 HTTP 巡檢
```bash
python3 - <<'PY'
import urllib.request
pages=[('/observability/overview','總覽'),('/observability/agent_orchestration','Agent'),('/observability/business_intel','商業'),('/observability/host_health','主機'),('/observability/ai_calls','AI 呼叫'),('/observability/budget','預算'),('/observability/promotion_review','晉升'),('/observability/rag_queries','RAG'),('/observability/quality_trend','品質'),('/observability/ppt_audit_history','PPT')]
needles=['Traceback','UndefinedError','ProgrammingError','Internal Server Error','relation "','查詢失敗:']
for path,label in pages:
with urllib.request.urlopen('https://mo.wooo.work'+path,timeout=12) as r:
html=r.read().decode('utf-8','ignore')
found=[n for n in needles if n in html]
print(f'{label}: HTTP {r.status}, issues={found or "none"}')
PY
```