Files
awoooi/docs/superpowers/plans/2026-04-08-sprint5-command-center-redesign.md

533 lines
18 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.
# Sprint 5 — 指令中心重設計:完整解決方案與細化實施步驟
> **建立**: 2026-04-08 (台北)
> **建立者**: Claude Code
> **狀態**: 📋 待統帥審核
> **技術選型**: ADR-060 React Flow + elkjs (已批准)
---
## 第一章:問題定義
### 1.1 現況問題
| 問題 | 具體描述 |
|------|---------|
| 首頁缺乏全局視角 | 目前首頁只有 Metrics Strip + Incident Feed + OpenClaw Panel無法一眼看清服務依賴關係 |
| 拓撲圖不存在 | `/topology` 頁面只有簡單的 host list沒有視覺化依賴圖 |
| 告警缺乏上下文 | 告警卡片不知道「這個服務影響了誰」 |
| AI 介入不透明 | 使用者不知道 OpenClaw 正在分析哪個服務 |
| 監控規模已達 67 實體 | 未來 120-150+,需要分層/聚焦能力 |
### 1.2 目標使用者
| 角色 | 使用場景 | 需要看到什麼 |
|------|---------|-------------|
| **統帥 (CIO)** | 每日巡檢、異常時指揮 | 全局健康度 → 異常在哪 → 該批准什麼 |
| **值班 SRE** | 告警響應、修復執行 | 哪個服務掛了 → 影響範圍 → 修復動作 |
| **管理層** | 週報/月報、ROI 評估 | 自動化率、MTTR 趨勢、處置分佈 |
### 1.3 成功標準
| 標準 | 量化目標 |
|------|---------|
| 發現異常 | 打開首頁 3 秒內能定位問題服務 |
| 理解影響 | 不用切換頁面就能看到依賴關係和爆炸半徑 |
| 執行修復 | 從發現到批准修復不超過 2 次點擊 |
| 資訊密度 | 一屏能呈現全局狀態,不需要捲動 |
---
## 第二章:解決方案概述
### 2.1 核心設計理念
**從「被動儀表板」到「主動指揮中心」**
```
傳統儀表板: 看數據 → 人腦判斷 → 手動操作
指令中心: 看全局 → AI 提供上下文 → 一鍵批准
```
### 2.2 頁面結構 (基於統帥截圖概念)
```
┌──────────────────────────────────────────────────────────┐
│ Header (68px): Logo + 頁面標題 + AI 狀態膠囊 + 語系 │
├──────────┬───────────────────────┬───────────────────────┤
│ Sidebar │ KPI Strip (4-5 指標) │ │
│ (224px) ├───────────────────────┤ 右側面板 (300px) │
│ │ │ ┌─────────────────┐ │
│ · 儀表板 │ 神經拓撲圖 │ │ 待核准任務 │ │
│ · 警報 │ (React Flow + elkjs) │ │ SSH URI + 按鈕 │ │
│ · 自動修復│ 嵌套群組/展開/收合 │ ├─────────────────┤ │
│ · 神經指揮│ │ │ 處置統計 │ │
│ · 腳本庫 │ │ │ 四色計數+堆疊條 │ │
│ · 知識庫 ├───────────────────────┤ └─────────────────┘ │
│ · 報表 │ 系統活動串流 (Live) │ │
│ · 審計 │ AI 推理過程時間軸 │ │
│ · 設定 ├───────────────────────┤ │
│ │ 控制列 (頻率/數據流) │ │
└──────────┴───────────────────────┴───────────────────────┘
```
### 2.3 五大區塊定義
| 區塊 | 位置 | 功能 | 資料來源 (API) |
|------|------|------|---------------|
| **KPI Strip** | 頂部橫條 | 系統健康度/活動事件/自動修復率/總操作 | `/dashboard` + `/stats/disposition` |
| **神經拓撲圖** | 中央主區域 | 服務依賴 + AI 介入 + 嵌套群組 | `/dashboard` (hosts/services) |
| **活動串流** | 中央下方 | 即時事件時間軸 (告警/AI/修復) | SSE `/events` |
| **待核准面板** | 右上 | SSH URI + 風險等級 + 批准/拒絕 | `/approvals/pending` |
| **處置統計** | 右下 | 四色計數 + 堆疊條 + 自動化率 | `/stats/disposition` |
---
## 第三章:拓撲圖詳細設計
### 3.1 嵌套群組結構
```
Level 0 (Macro View) — 預設顯示4-6 個群組節點
├── 基礎設施 (.110) [藍色邊框]
│ └── 收合時顯示: "5 服務 · 全部健康"
├── AI/數據中心 (.188) [紅色邊框 if 異常]
│ └── 收合時顯示: "10 服務 · 1 警告"
├── K3s 叢集 (120/121) [紫色邊框]
│ └── 收合時顯示: "15 Pods · 全部運行"
└── 外部網路 [橘色邊框]
└── 收合時顯示: "6 目標 · 全部可達"
Level 1 (Drill-down) — 點擊群組展開
├── .110 展開後:
│ ├── Gitea (3001) ── 健康
│ ├── Harbor (5000) ── 健康
│ ├── Sentry (9000) ── 健康
│ ├── Prometheus (9090) ── 健康
│ ├── Alertmanager (9093) ── 健康
│ └── Grafana ── 健康
├── .188 展開後:
│ ├── PostgreSQL (5432) ── 健康
│ ├── Redis (6380) ── 健康
│ ├── OpenClaw (8089) ── [AI 診斷中 ⚡]
│ ├── Ollama (11434) ── 健康
│ ├── SignOz (3301) ── 健康
│ ├── ClickHouse (8123) ── 健康
│ ├── MinIO (9000) ── 健康
│ └── Langfuse (3100) ── 健康
...
```
### 3.2 節點設計 (React Flow Custom Node)
```
┌─────────────────────────┐
│ ● healthy │ ← 狀態燈 + 文字
│ PostgreSQL │ ← 服務名稱 (Inter 600)
│ .188:5432 · Docker │ ← 位置 + 類型 (JetBrains Mono 9px)
└─────────────────────────┘
圓角 8px · 0.5px 邊框 · card shadow
狀態顏色:
● 綠色 (#22C55E) = healthy
● 橘色 (#F59E0B) = warning (CPU/Memory 偏高)
● 紅色 (#cc2200) = critical (服務不可用)
● 藍色 (#4A90D9) = AI 正在診斷
● 灰色 (#A3A3A3) = unknown
```
### 3.3 邊線設計
| 類型 | 樣式 | 用途 |
|------|------|------|
| 正常依賴 | 綠色漸層 → 透明,實線 | 健康的服務間連線 |
| 異常依賴 | 橘色→紅色漸層,虛線 | 受影響的依賴鏈 |
| AI 介入 | 藍色→紫色漸層,流動粒子動畫 | OpenClaw 正在分析的路徑 |
| 收合群組間 | 灰色虛線 | 群組之間的連線 |
### 3.4 互動行為
| 操作 | 行為 |
|------|------|
| 點擊群組 | 展開/收合群組,顯示內部服務 |
| 點擊服務節點 | 右側面板顯示該服務詳情 (指標/日誌/告警) |
| Hover 節點 | 顯示 tooltip (CPU/Memory/連線數) |
| 滾輪 | 縮放 |
| 拖曳空白 | 平移畫布 |
| 「全部展開」按鈕 | 展開所有群組 |
| 「全部收合」按鈕 | 收合到 Macro View |
| 「只看異常」按鈕 | 隱藏所有健康節點,只顯示 warning/critical |
---
## 第四章:細化實施步驟
### Phase 1: 基礎建設 (Day 1)
#### Task 1.1: 安裝依賴
```bash
cd apps/web
npm install @xyflow/react elkjs
```
**驗證**: `import { ReactFlow } from '@xyflow/react'` 能成功 import
**檔案影響**: `package.json`, `package-lock.json`
---
#### Task 1.2: 建立 topology 元件目錄結構
```
apps/web/src/components/topology/
├── index.ts # 匯出
├── ServiceTopology.tsx # 主元件
├── nodes/
│ ├── GroupNode.tsx # 群組節點 (可展開/收合)
│ ├── ServiceNode.tsx # 服務節點 (memo)
│ └── node-types.ts # nodeTypes 註冊
├── edges/
│ ├── TopologyEdge.tsx # 自定義邊線 (漸層+動畫)
│ └── edge-types.ts # edgeTypes 註冊
├── hooks/
│ ├── useTopologyData.ts # API → nodes/edges 轉換
│ └── useElkLayout.ts # elkjs 佈局引擎
├── utils/
│ ├── topology-colors.ts # 狀態→顏色映射 (從 tailwind.config.ts)
│ └── topology-icons.ts # 服務→Lucide icon 映射
└── topology.css # 邊線動畫 keyframes
```
**驗證**: 目錄結構正確建立
---
### Phase 2: 核心元件 (Day 2-3)
#### Task 2.1: ServiceNode.tsx — 服務節點
```typescript
// 關鍵設計決策:
// 1. 用 React.memo + 自定義 areEqual
// 2. Tailwind className 直接套用
// 3. Lucide icon 根據服務類型選擇
// 4. 狀態色彩從 topology-colors.ts
```
**檔案**: `apps/web/src/components/topology/nodes/ServiceNode.tsx`
**測試**: 渲染 1 個節點,確認 Tailwind 樣式 + Lucide icon 正確
**i18n**: 節點標籤用 `useTranslations('topology')`
---
#### Task 2.2: GroupNode.tsx — 群組節點
```typescript
// 關鍵設計決策:
// 1. 收合時: 顯示群組名稱 + 服務數 + 健康摘要
// 2. 展開時: 變成透明容器,內部由 elkjs 排列子節點
// 3. 邊框顏色: 藍(.110) / 紅(.188異常) / 紫(K3s) / 橘(外部)
// 4. 點擊標題列 toggle 展開/收合
```
**檔案**: `apps/web/src/components/topology/nodes/GroupNode.tsx`
**測試**: 收合→展開→收合 循環測試
---
#### Task 2.3: TopologyEdge.tsx — 自定義邊線
```typescript
// 關鍵設計決策:
// 1. 用 React Flow 的 BaseEdge + getSmoothStepPath
// 2. SVG linearGradient 漸層色
// 3. CSS stroke-dasharray 流動動畫 (零 JS 開銷)
// 4. AI 介入路徑: 藍紫漸層 + 粒子動畫 (SVG animateMotion)
```
**檔案**: `apps/web/src/components/topology/edges/TopologyEdge.tsx`
**檔案**: `apps/web/src/components/topology/topology.css`
**測試**: 三種邊線 (正常/異常/AI) 渲染正確
---
#### Task 2.4: useElkLayout.ts — elkjs 佈局引擎
```typescript
// 關鍵設計決策:
// 1. elkjs 異步執行 — 需要 loading 狀態
// 2. 群組嵌套: elk options { 'elk.algorithm': 'layered' }
// 3. 節點間距: nodeSpacing=20, layerSpacing=50
// 4. 邊線路由: 'elk.edgeRouting': 'ORTHOGONAL' (正交)
// 5. 方向: 'elk.direction': 'RIGHT' (左到右)
```
**檔案**: `apps/web/src/components/topology/hooks/useElkLayout.ts`
**測試**: 輸入 20 個節點,輸出合理的 x/y 座標
---
#### Task 2.5: useTopologyData.ts — API 資料轉換
```typescript
// 關鍵設計決策:
// 1. 從 /api/v1/dashboard 取得 hosts + services
// 2. 轉換為 React Flow 的 Node[] + Edge[] 格式
// 3. 加入 parentId 實現嵌套 (elkjs compound graph)
// 4. 節點狀態即時更新 (透過 Zustand store 或定時 polling)
```
**檔案**: `apps/web/src/components/topology/hooks/useTopologyData.ts`
**測試**: API 回傳 → 正確的 nodes/edges 結構
---
### Phase 3: 主元件組裝 (Day 3-4)
#### Task 3.1: ServiceTopology.tsx — 主元件
```typescript
// 組裝所有子元件:
// 1. ReactFlow + nodeTypes + edgeTypes
// 2. useTopologyData (API 資料)
// 3. useElkLayout (佈局計算)
// 4. 控制列 (全部展開/收合/只看異常)
// 5. MiniMap + Controls
// 6. 骨架屏 (elkjs 計算中顯示)
```
**檔案**: `apps/web/src/components/topology/ServiceTopology.tsx`
**測試**: 完整拓撲圖渲染 + 互動
---
#### Task 3.2: i18n 翻譯
```json
// messages/zh-TW.json
{
"topology": {
"title": "神經拓撲",
"expandAll": "全部展開",
"collapseAll": "全部收合",
"showAnomaliesOnly": "只看異常",
"healthy": "健康",
"warning": "警告",
"critical": "異常",
"aiDiagnosing": "AI 診斷中",
"services": "服務",
"pods": "Pods",
"allHealthy": "全部健康",
"infraGroup": "基礎設施",
"aiGroup": "AI/數據中心",
"k3sGroup": "K3s 叢集",
"externalGroup": "外部網路"
}
}
```
**檔案**: `messages/zh-TW.json`, `messages/en.json`
---
### Phase 4: 頁面整合 (Day 4-5)
#### Task 4.1: 首頁 `/` 整合
```
修改: apps/web/src/app/[locale]/page.tsx
新增: ServiceTopology 元件到中央區域
保留: 現有 Metrics Strip + Incident Feed + OpenClaw Panel
策略: 拓撲圖收合模式 (Macro View4-6 群組節點)
```
---
#### Task 4.2: 拓撲頁 `/topology` 升級
```
修改: apps/web/src/app/[locale]/topology/page.tsx
替換: 現有 host list → 完整 ServiceTopology (可展開)
新增: 篩選器 (按群組/狀態/服務類型)
```
---
#### Task 4.3: 神經指揮 `/neural-command` 整合
```
修改: apps/web/src/components/neural-command/NeuralLiveCenter.tsx
新增: 迷你版 ServiceTopology (SSH 指揮鏈視圖)
```
---
### Phase 5: 設計稿與視覺調校 (Day 5-6)
#### Task 5.1: HTML Mockup 製作 (3+ 版本)
差異化在佈局比例和視覺重心:
| 版本 | 差異 | 拓撲佔比 | 右面板 |
|------|------|---------|--------|
| VA | 拓撲主角 + 右側固定面板 | 65% | 待核准 + 統計 |
| VB | 拓撲+串流並排 + 右側 tab 切換 | 55% | tab: 核准/串流/統計 |
| VC | 拓撲全幅 + 底部折疊面板 | 80% | 底部抽屜式 |
**部署**: scp → 192.168.0.188 → http://192.168.0.188:8765/
---
#### Task 5.2: 統帥選擇後視覺調校
根據統帥回饋修改:
- 佈局比例
- 配色微調
- 互動細節
---
### Phase 6: 後端 API 支援 (Day 6-7)
#### Task 6.1: `/api/v1/dashboard` 擴充
```python
# 現有回傳: hosts (name, status, cpu, ram, services)
# 需擴充:
# 1. 每個 host 加入 group 分類 (infra/ai/k3s/external)
# 2. 服務間的依賴關係 (edges)
# 3. AI 介入狀態 (openclaw_diagnosing: [service_name])
```
**檔案**: `apps/api/src/api/v1/dashboard.py`
**檔案**: `apps/api/src/services/dashboard_service.py` (如果有)
---
#### Task 6.2: 服務依賴關係定義
```yaml
# 可能需要新增 ConfigMap 或靜態配置
# 定義哪些服務依賴哪些服務
dependencies:
awoooi-web → awoooi-api
awoooi-api → postgresql, redis, openclaw
awoooi-worker → postgresql, redis, ollama
openclaw → ollama, langfuse
...
```
**方案選擇**:
- A: 靜態配置 (YAML/JSON) — 簡單可控
- B: 從 OTEL Trace 自動推導 — 動態但複雜
- C: 從 K8s NetworkPolicy 推導 — 部分覆蓋
**建議**: 先 A (靜態配置),未來可加 B (OTEL 自動發現)
---
### Phase 7: 測試與驗收 (Day 7-8)
#### Task 7.1: TypeScript 驗證
```bash
cd apps/web && pnpm exec tsc --noEmit
```
#### Task 7.2: 生產建置
```bash
pnpm run build
```
#### Task 7.3: 視覺驗收
- 首頁拓撲圖收合模式
- 點擊展開每個群組
- AI 介入動畫
- 異常節點高亮
- 響應式 (收合 Sidebar 後拓撲圖自動調整)
#### Task 7.4: 效能驗收
- 40+ 節點全展開時 FPS ≥ 30
- elkjs 佈局計算 ≤ 500ms
- 單一節點狀態更新不觸發其他節點 re-render
---
## 第五章:風險與緩解
| 風險 | 等級 | 緩解 |
|------|------|------|
| elkjs API 學習成本 | 中 | 封裝在 useElkLayout.ts只暴露 layoutNodes() |
| elkjs 佈局計算阻塞 UI | 低 | Web Worker 或 setTimeout 分片 |
| 節點數 150+ DOM 效能 | 低 | 預設收合 (只 4-6 DOM),展開時 memo |
| 服務依賴定義維護 | 中 | 先靜態 YAML未來 OTEL 自動發現 |
| 設計與現有頁面衝突 | 低 | 拓撲圖是新增元件,不動現有佈局 |
---
## 第六章:時程預估
| Phase | 天數 | 內容 |
|-------|------|------|
| 1 | 1 | 安裝依賴 + 目錄結構 |
| 2 | 2 | 核心元件 (節點/邊線/佈局/資料) |
| 3 | 1 | 主元件組裝 + i18n |
| 4 | 1 | 頁面整合 (首頁/拓撲/神經指揮) |
| 5 | 2 | 設計稿 (3+版本) + 視覺調校 |
| 6 | 1 | 後端 API 擴充 |
| 7 | 1 | 測試 + 驗收 |
| **總計** | **~9 天** | |
---
## 第七章:需要統帥決策的事項
| # | 決策項 | 選項 | 建議 | 統帥決定 |
|---|--------|------|------|---------|
| 1 | 首頁拓撲圖佈局比例 | 65% / 55% / 80% | 待設計稿比較 | ⏳ |
| 2 | 右側面板模式 | 固定 / tab切換 / 底部抽屜 | 待設計稿比較 | ⏳ |
| 3 | 服務依賴定義方式 | 靜態YAML / OTEL自動 / 混合 | 先靜態 | ⏳ |
| 4 | 拓撲圖預設狀態 | 全部收合 / 展開異常群組 | 展開異常 | ⏳ |
| 5 | 是否先做 PoC 驗證 | 先 PoC 再做設計稿 / 並行 | 先 PoC | ⏳ |
---
## 第八章:需要的技術文檔 (輔助決策)
為了讓統帥能做出更完整的決策,以下文檔需要準備:
| # | 文檔 | 用途 | 狀態 |
|---|------|------|------|
| 1 | **React Flow + elkjs PoC Demo** | 在內網部署一個可互動的 PoC讓統帥親手操作展開/收合/篩選 | ⏳ 待製作 |
| 2 | **競品 UI 截圖集** | Datadog Service Map / Dynatrace Smartscape / Grafana Node Graph 的真實產品截圖 | ⏳ 待收集 |
| 3 | **3+ 版本 HTML 設計稿** | 高品質 mockup 部署到內網 192.168.0.188:8765 | ⏳ 待製作 |
| 4 | **現有 API 回傳格式文件** | `/api/v1/dashboard` 目前回傳什麼、需要擴充什麼 | ⏳ 待整理 |
| 5 | **服務依賴關係圖** | 67 個實體的完整依賴關係 (手動整理) | ⏳ 待整理 |
| 6 | **Bundle Size 影響報告** | 安裝 @xyflow/react + elkjs 後的 bundle 增量 | ⏳ 待測量 |
---
## 第九章:建議下一步
**統帥,我建議按以下順序推進:**
```
Step 1: 先做 PoC (React Flow + elkjs 嵌套群組)
→ 部署到內網讓統帥實際操作
→ 確認技術可行性和互動體驗
Step 2: 收集競品截圖 + 整理服務依賴關係
→ 給統帥參考市場做法
Step 3: 基於 PoC + 競品 → 製作 3+ 版本設計稿
→ 統帥選擇方向
Step 4: 確認方向後 → 正式實作 (Phase 1-7)
```
**統帥,這份計畫是否足夠完整?還需要補充哪些內容?**