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

14 KiB
Raw Blame History

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

策略:一次性掃描→批量修復,非逐一處理

# 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

// ❌ 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')
}
// ❌ 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')
}

需要同步更新的字典檔

// apps/web/messages/zh-TW.json追加
{
  "status": {
    "idle": "待機",
    "thinking": "分析中",
    "executing": "執行中",
    "awaitingApproval": "等待核准",
    "error": "錯誤",
    "standby": "待機",
    "analyzing": "分析中"
  }
}
// apps/web/messages/en.json追加
{
  "status": {
    "idle": "Idle",
    "thinking": "Thinking",
    "executing": "Executing",
    "awaitingApproval": "Awaiting Approval",
    "error": "Error",
    "standby": "Standby",
    "analyzing": "Analyzing"
  }
}

驗收指令(必須通過)

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 視覺感知盲區的根本方案

# 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-pingcritical 時) 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

// 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 自主截圖並等待統帥審核:

## 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
  1. 截圖存至 docs/screenshots/{date}/{component}.png
  2. 在 LOGBOOK 記錄:「已截圖,視覺存檔 docs/screenshots/xxx/yyy.png」
  3. 等待統帥視覺審批後方可 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 事件處理器(關鍵)

// 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

// 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 合併前,必須通過以下全部驗收:

# 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 之前執行

# 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 緊急流程

# 情境簽核按鈕在生產失效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 分鐘