Files
ewoooc/docs/guides/observability_ui_governance.md
OoO 3fca720fa1
Some checks failed
CD Pipeline / deploy (push) Failing after 2m11s
test(observability): guard sidebar navigation design
2026-05-05 15:41:39 +08:00

3.7 KiB
Raw Blame History

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-sizeKPI 數字使用 --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 頁巡檢不得出現 TracebackUndefinedErrorProgrammingErrorrelation "查詢失敗:

驗收指令

1. Repo 靜態 UI guard

先跑本地 guard避免把已知 UI/UX 回歸重新帶進 repo

scripts/check_observability_suite.sh

若只想跑靜態檢查:

python3 scripts/check_observability_ui.py

或透過既有 quick review 選單執行第 8 項完整 QA 套件、第 6 項靜態 UI guard

./scripts/quick_review.sh

Guard 會檢查:

  • Times / Georgia 等非規範標題字型。
  • SQL/Jinja exception 文案外露。
  • 圖表 style="height:..." 與靜態 style="width:..."
  • 過大標題 clamp 與純白 hover/card surface。
  • 觀測台 CSS 必要 token / utility class 是否仍存在。
  • 側欄是否維持 AI 中樞 → AI 觀測台 → 分組頁面 的收納結構。
  • 側欄是否維持暖深咖啡背景與第二/三層足夠對比。
  • Topbar 是否仍載入觀測台 CSS 與健康 indicator。

2. Production 10 頁 HTTP 巡檢

建議使用 repo 內建腳本:

python3 scripts/check_observability_pages.py

或透過 quick review 選單執行第 7 項。

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