Files
awoooi/docs/runbooks/RUNBOOK-FRONTEND-UIUX-SOVEREIGNTY.md
OG T 89e05e6ea2 docs: ADR-037 + 監控架構提案 + Runbooks
- ADR-037 監控增強架構
- MONITORING_MASTER_PLAN 主計畫
- MASTER_EXECUTION_SCHEDULE 執行排程
- Phase D/E/Worker HPA Runbooks

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-29 16:04:08 +08:00

500 lines
14 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.
# RunBook: 前端 UI/UX 核心痛點徹底解決方案
> **類型**: 架構設計 + 實施 RunBook
> **優先級**: 🔴 P0 (核心競爭力)
> **建立**: 2026-03-29 12:38 (台北)
> **建立者**: Antigravity
> **核心命題**: 讓 AWOOOI 的前端「讓人看一眼就驚艷,用一次就上癮」
---
## 一、Claude Code 前端弱點診斷
### 1.1 五大結構性弱點
| 弱點 | 後果 | 解法 |
|------|------|------|
| **視覺感知盲區** | 代碼語法正確,但視覺效果差 | Playwright 截圖 + 統帥視覺主控 |
| **CSS 語境失憶** | 改 A 壞 B不知道全局 CSS 影響 | Storybook 隔離組件 + TypeCheck |
| **動畫設計無感** | 150ms 快閃 vs 300ms 遲滯無法感知 | 在 Storybook Story 中定義動畫標準 |
| **設計意圖推斷不足** | Nothing.tech 審美需要視覺參照 | 每個組件附帶規格截圖 |
| **Safari 兼容性盲點** | `backdrop-blur` 在 Safari 有 bug | Playwright multi-browser E2E |
### 1.2 技術債現況(截至 2026-03-29
```
i18n 違規40+ 處TECHNICAL_DEBT_PHASE2.md
shadcn/ui 殘留:已部分廢除,但需全面確認
GenUI Registry只有基礎 5 張卡片,缺少監控類
Knowledge Base頁面空白無後端
Omni-Terminal外殼完整SSE 事件類型未完全對接
```
---
## 二、九大行動詳細實施計畫
### 🔴 行動 1: i18n 閃電清零工時4h
**策略:一次性掃描→批量修復,非逐一處理**
```bash
# Step 1.1: 自動掃描所有硬編碼字串
cd /Users/ogt/awoooi/apps/web
# 掃描 TSX 中的英文硬編碼(排除技術識別符)
grep -rn '"[A-Z][A-Z]' src/ --include="*.tsx" --include="*.ts" | \
grep -v "//.*\"" | \
grep -v "className=" | \
grep -v "href=" | \
grep -v "id=" | \
grep -v "import " > /tmp/en_violations.txt
# 掃描中文硬編碼
grep -rn "\"[^\x00-\x7F]" src/ --include="*.tsx" | \
grep -v "//.*\"" > /tmp/zh_violations.txt
echo "英文違規:$(wc -l < /tmp/en_violations.txt)"
echo "中文違規:$(wc -l < /tmp/zh_violations.txt)"
```
**已知 P0 違規快速修復清單**(根據 TECHNICAL_DEBT_PHASE2.md
```typescript
// ❌ agent/data-pincer.tsx:50-78需修復
// 現在:
const statuses = {
standby: 'STANDBY',
analyzing: 'ANALYZING',
executing: 'EXECUTING',
awaiting: 'AWAITING APPROVAL',
error: 'ERROR'
}
// ✅ 修復後:
const statuses = {
standby: t('status.standby'),
analyzing: t('status.analyzing'),
executing: t('status.executing'),
awaiting: t('status.awaitingApproval'),
error: t('status.error')
}
```
```typescript
// ❌ status-orb.tsx:16-31
// 現在:
const STATUS_TEXT = {
idle: 'Idle',
thinking: 'Thinking',
executing: 'Executing',
awaiting: 'Awaiting Approval'
}
// ✅ 修復後:
const STATUS_TEXT = {
idle: t('status.idle'),
thinking: t('status.thinking'),
executing: t('status.executing'),
awaiting: t('status.awaitingApproval')
}
```
**需要同步更新的字典檔**
```json
// apps/web/messages/zh-TW.json追加
{
"status": {
"idle": "待機",
"thinking": "分析中",
"executing": "執行中",
"awaitingApproval": "等待核准",
"error": "錯誤",
"standby": "待機",
"analyzing": "分析中"
}
}
```
```json
// apps/web/messages/en.json追加
{
"status": {
"idle": "Idle",
"thinking": "Thinking",
"executing": "Executing",
"awaitingApproval": "Awaiting Approval",
"error": "Error",
"standby": "Standby",
"analyzing": "Analyzing"
}
}
```
**驗收指令(必須通過)**
```bash
cd apps/web
# 確認無中文硬編碼
if grep -rn '"[^\x00-\x7F]' src/ --include="*.tsx" | grep -v "//"; then
echo "❌ 仍有中文硬編碼!"
exit 1
else
echo "✅ 中文硬編碼清零"
fi
# TypeScript 編譯驗證workflow 硬規則)
pnpm exec tsc --noEmit
```
---
### 🔴 行動 2: Storybook 組件庫建立工時8h
**這是解決 AI 視覺感知盲區的根本方案**
```bash
# Step 2.1: 安裝 Storybook
cd apps/web
pnpm add -D storybook@latest @storybook/nextjs @storybook/addon-essentials \
@storybook/addon-interactions @storybook/test
npx storybook@latest init --builder webpack5
# Step 2.2: 配置 Nothing.tech 主題
```
**必須上架的 10 個核心組件 Story**
| 組件 | Nothing.tech 規格 | Story 狀態 |
|------|-----------------|-----------|
| `GlassCard` | `bg-white/70 backdrop-blur-[20px] border border-black/[0.06]` | Loading / Content / Error |
| `StatusOrb` | 燈號 + `animate-ping`critical 時)| idle / thinking / executing / critical |
| `ApprovalCard` | 1.0 ConversationalView 風格 | LOW / MEDIUM / HIGH / CRITICAL |
| `OmniTerminal` | VT323 字體 + 綠色游標閃爍 | empty / thinking / streaming / error |
| `HostCard` | CPU/Memory 橫條 + 脈搏點 | healthy / warning / critical |
| `MetricsCard` | 數字大字 + 趨勢箭頭 | up / down / stable |
| `SystemHealthCard` | 燈號矩陣 5x5 | all-healthy / some-warning / critical |
| `FinOpsCard` | 成本分解 + 可省金額 | monthly / quarterly |
| `SLOCard` | 達成率 + 趨勢 | healthy / at-risk / breached |
| `AnomalyFrequencyCard` | 頻率統計 + 升級建議 | normal / repeat / escalate |
**Storybook Story 範例**GlassCard
```typescript
// apps/web/src/components/ui/glass-card.stories.ts
import type { Meta, StoryObj } from '@storybook/react';
import { GlassCard } from './glass-card';
const meta: Meta<typeof GlassCard> = {
title: 'AWOOOI/UI/GlassCard',
component: GlassCard,
parameters: {
// Nothing.tech 白底背景
backgrounds: {
default: 'nothing-white',
values: [{ name: 'nothing-white', value: '#F5F5F0' }],
},
// 規格文件截圖
docs: {
description: {
component: `
Nothing.tech 白玻璃卡片。固定規格:
- bg: bg-white/70
- blur: backdrop-blur-[20px]
- border: border border-black/[0.06]
- radius: rounded-xl
`,
},
},
},
tags: ['autodocs'],
};
export default meta;
type Story = StoryObj<typeof GlassCard>;
export const Default: Story = {
args: { children: '玻璃卡片內容' }
};
export const WithCriticalBorder: Story = {
args: {
children: '緊急狀態',
className: 'border-status-critical border-2'
}
};
```
---
### 🔴 行動 3: AI 視覺審查 SOP工時2h 建立,後續 0 工時)
**建立標準作業程序,讓 AI 自主截圖並等待統帥審核:**
```markdown
## AI 前端修改 SOP強制執行
### 修改前
1. 查閱 Storybook 對應組件的規格 Story
2. 確認 Nothing.tech 視覺 Token詳見 tailwind.config.ts
### 修改中
3. 修改代碼
4. 執行 `pnpm exec tsc --noEmit`(語法驗證)
### 修改後(🆕 新增強制步驟)
5. 啟動 Dev Server`pnpm dev`
6. 執行截圖腳本:
```bash
cd apps/web
pnpm exec playwright screenshot \
--browser chromium \
http://localhost:3000 \
docs/screenshots/$(date +%Y%m%d-%H%M)/homepage.png
```
7. 截圖存至 `docs/screenshots/{date}/{component}.png`
8. 在 LOGBOOK 記錄:「已截圖,視覺存檔 docs/screenshots/xxx/yyy.png」
9. 等待統帥視覺審批後方可 commit
```
---
### 🟠 行動 4: Omni-Terminal 後端全接通工時8h
根據 `ADR-031``AWOOOI_AGENTIC_WORKSPACE_ROADMAP.md` 的神經連接藍圖:
#### 4.1 三大 SSE 事件類型定義
```python
# apps/api/src/api/v1/terminal.py
# 擴充現有 SSE 端點
class SSEEventType(str, Enum):
THOUGHT = "thought" # Agent 思考流
TOOL_CALL = "tool_call" # 工具調用(含微動畫觸發信號)
TOOL_RESULT = "tool_result" # 工具結果
RENDER_UI = "render_ui" # 動態渲染 GenUI 組件
STREAM_END = "stream_end" # 思考流結束
# 範例事件:
async def stream_terminal_response(command: str):
# 1. 思考流
yield f"event: thought\ndata: {json.dumps({'text': '[Investigator] 分析指令...'})}\n\n"
# 2. 工具調用(觸發前端 CSS 動畫)
yield f"event: tool_call\ndata: {json.dumps({'tool': 'kubectl_get', 'args': {'resource': 'pod', 'namespace': 'awoooi-prod'}})}\n\n"
# 3. 工具結果
yield f"event: tool_result\ndata: {json.dumps({'pods': [...]})}\n\n"
# 4. 渲染 GenUI 卡片(前端動態載入組件)
yield f"event: render_ui\ndata: {json.dumps({'component': 'SystemHealthCard', 'props': {...}})}\n\n"
# 5. 結束
yield f"event: stream_end\ndata: {json.dumps({'success': True})}\n\n"
```
#### 4.2 前端 SSE 事件處理器(關鍵)
```typescript
// apps/web/src/hooks/useTerminalSSE.ts
// 修改現有 SSE hook增加 tool_call 動畫觸發
const useTerminalSSE = (commandId: string) => {
const [state, setState] = useTerminalStore();
useEffect(() => {
const es = new EventSource(`/api/v1/terminal/stream/${commandId}`);
// 思考流
es.addEventListener('thought', (e) => {
const data = JSON.parse(e.data);
setState(s => ({ ...s, thoughts: [...s.thoughts, data.text] }));
});
// 工具調用 → 觸發微動畫
es.addEventListener('tool_call', (e) => {
const data = JSON.parse(e.data);
setState(s => ({
...s,
activeToolCall: data.tool, // UI 顯示「正在執行 kubectl_get...」
isAnimating: true
}));
});
// GenUI 動態渲染(核心功能!)
es.addEventListener('render_ui', (e) => {
const { component, props } = JSON.parse(e.data);
setState(s => ({
...s,
renderedCards: [...s.renderedCards, { component, props }]
}));
});
es.addEventListener('stream_end', () => {
setState(s => ({ ...s, isStreaming: false, isAnimating: false }));
es.close();
});
return () => es.close();
}, [commandId]);
};
```
---
### 🟠 行動 5: GenUI Registry 擴充工時8h
新增 5 張監控類 GenUI 卡片(詳細規格見 `MONITORING_ARCHITECTURE_DEEP_DIVE.md`
```typescript
// apps/web/src/components/genui/registry.ts
export const GENUI_COMPONENTS = {
// 現有:
'MetricsCard': () => import('./cards/MetricsCard'),
'K8sPodCard': () => import('./cards/K8sPodCard'),
// 🆕 監控類Wave M-3
'SystemHealthCard': () => import('./monitoring/SystemHealthCard'),
'ServiceDetailCard': () => import('./monitoring/ServiceDetailCard'),
'FinOpsCard': () => import('./monitoring/FinOpsCard'),
'SLODashboardCard': () => import('./monitoring/SLODashboardCard'),
'AlertChainStatusCard': () => import('./monitoring/AlertChainStatusCard'),
'AnomalyFrequencyCard': () => import('./monitoring/AnomalyFrequencyCard'),
'MTTRCard': () => import('./monitoring/MTTRCard'),
}
```
---
## 三、前端改善路線圖時間表
```
📅 本週(立即):
[4h] i18n 閃電清零(一次性全修)
[2h] AI 視覺審查 SOP 建立(.awoooi-agent-rules.md 追加)
📅 Week 2-3
[8h] Storybook 10 個核心組件 Story
[8h] Omni-Terminal 後端全接通(三種 SSE 事件)
📅 Week 4-5
[8h] 監控 GenUI 卡片擴充7 張新卡片)
[8h] Nexus 頁面 AI 自治率 UI 組件
📅 Month 2
[16h] Knowledge Base 後端 + 前端完整建設
[8h] Visual Regression Testing CI 整合
📅 Month 3Phase 4 視覺靈魂注入):
[?h] 品牌 3D 資產 + Q 版 OpenClaw
[?h] 全站微動畫升級150ms 快閃標準)
[?h] Nothing.tech 認證級別的設計審計
```
---
## 四、強制驗收標準
每次前端 PR 合併前,必須通過以下全部驗收:
```bash
# 1. TypeScript 無錯誤(前端美學 Workflow 硬規則)
cd apps/web && pnpm exec tsc --noEmit
# 2. i18n 無硬編碼CI 攔截)
[ -z "$(grep -rn '"[^\x00-\x7F]' src/ --include='*.tsx')" ] || exit 1
# 3. Storybook 可正常 build確保組件獨立可用
pnpm storybook build
# 4. E2E Smoke 測試通過
pnpm exec playwright test --grep @smoke
# 5. 截圖存檔AI 執行,統帥視覺審批)
pnpm exec playwright screenshot http://localhost:3000 docs/screenshots/pr-{NUMBER}/homepage.png
# 6. Build 成功(生產環境兼容)
pnpm run build
```
---
## ⚠️ 架構安全補丁2026-03-29 更新,行動 1 開始前必讀)
> 來源:`ARCHITECTURAL_RISK_WAR_GAME.md` 深度沙盤推演,代碼確認級別
### 補丁Feature Freeze 前必須建立 release/v1.x 穩定分支
**問題**:行動 1i18n 閃電清零)需要全域替換 `src/` 底下數千行代碼,`main` 分支會進入持續 3-5 天的「混沌狀態」。若此期間生產爆發 P0 Bug如簽核按鈕失效**無法切出乾淨的 Hotfix 分支**,導致修復與重構互相衝突。
> 🔴 **行動 1 開始前,必須先建立 `release/v1.x` 穩定分支!**
#### 必須在行動 1 之前執行
```bash
# Step 0行動 1 前置):建立穩定基準分支
git checkout main
git pull origin main
git checkout -b release/v1.x
git push origin release/v1.x
# 在 GitHub 設定 release/v1.x 為 Protected Branch
# Settings → Branches → Add branch protection rule → release/v1.x
# ✅ Require pull request reviews (1 approver)
# ✅ Do not allow bypassing the above settings
```
#### 正確的行動順序
```
Step 0建立 release/v1.x🆕 前置步驟,必須先做)
Step 1宣佈 Frontend Feature Freeze禁止非 i18n PR 合併前端代碼)
Step 2i18n 閃電清零(在 fix/i18n-zero-violation 分支進行)
Step 3PR 合併到 main → 解除 Frontend Freeze
Step 4ESLint i18n Plugin 切換為 error 模式
Step 5繼續行動 2-9Storybook、Terminal 等)
```
#### Freeze 期間 P0 Hotfix 緊急流程
```bash
# 情境簽核按鈕在生產失效i18n 清零正在進行中
# 1. 從穩定基準切出 hotfix不影響 i18n 重構)
git checkout release/v1.x
git checkout -b hotfix/fix-approval-button
# 2. 最小化修復(只改 Bug不動其他代碼
# ... 修復代碼 ...
git add . && git commit -m "fix: approval button not responding on mobile"
# 3. PR 到 release/v1.x → CD 直接部署 release 分支
git push origin hotfix/fix-approval-button
# → PR 合併到 release/v1.x
# → 觸發 CD 部署CD 配置需支援 release/* 分支)
# 4. Cherry-pick 到 main不中斷 i18n 重構)
git checkout main
git cherry-pick <hotfix-commit-hash>
# 若有衝突:手動解決後繼續
```
#### Hotfix 觸發條件(須加入 HARD_RULES.md
```
P0 Hotfix 判定標準(任一條件符合即觸發):
□ 統帥無法使用核心功能簽核按鈕、登入、Telegram 通知)
□ Sentry P0 Error 每分鐘 > 10 次
□ 服務 availability < 99%(監控頁面顯示)
□ OpenClaw 決策鏈完全中斷超過 5 分鐘
```