# Sprint F: 前端打假行動 (Fake Data Purge)

> **建立**: 2026-04-07 (台北時區)
> **建立者**: Claude Code
> **首席架構師審查**: ✅ 100% Fully Approved (統帥原話: "請立即啟動實作程序")
> **優先級**: 🔴 P0 — 直接影響系統可信度 (Trust)

---

## 背景

前端審計發現 **29 處假數據/假頁面**，嚴重違反 `feedback_no_fake_data.md` 鐵律。
核心問題: Neural Command 頁面後端 API 已全部打通 (Sprint 2/3)，但前端子組件殘留大量 Mock 常數。

## 與現有工作的衝突分析

| 現有工作 | 衝突? | 分析 |
|----------|-------|------|
| Sprint 3 SSH_COMMAND (已完成) | ❌ 無衝突 | Sprint F 修復的正是 Sprint 3 前端組件的假數據 |
| Sprint 4 告警處置統計 (待實作) | ⚠️ 低衝突 | Sprint 4 Phase E (前端頁面) 會新增組件，Sprint F 修的是現有組件。建議 **Sprint F 先做**，確保新組件從一開始就用真實數據 |
| Phase 24 AI Router (進行中) | ❌ 無衝突 | 後端路由重構，不涉及前端 |
| Phase O 可觀測性 | ❌ 無衝突 | SigNoz/監控整合，不涉及 Neural Command UI |

**結論**: Sprint F 應在 Sprint 4 Phase A 之前執行，作為 Sprint 3.5 的技術債清理。

---

## 執行順序

```
Sprint 3 (✅ 完成) → Sprint F (打假行動) → Sprint 4 (告警處置統計)
                      ^^^^^^^^^^^^^^^^
                      當前執行點
```

---

## Phase P0: Neural Command 假數據清除 (核心修復)

### P0-1: NeuralLiveCenter.tsx

**問題**: 6 處假數據 + 假歷史 + 假告警雷達
**後端 API**: 已有 `stats` + `history` props 從 page.tsx 傳入

| 修復項 | 現況 (假) | 修復方案 |
|--------|-----------|----------|
| L51-57: `displayHistory` fallback | 5 筆假 INC-1~5 | 無資料時顯示 `EmptyState` (`t('noHistory')`) |
| L77: todayMatches | 寫死 `23` | 從 `stats` 計算或顯示 `--` |
| L78: RAG Confidence | 寫死 `0.87` | 從 `stats` 取或顯示 `--` |
| L93: 執行成功率 | 寫死 `136/156` | `stats.total_executions * stats.overall_success_rate / stats.total_executions` |
| L94: 平均時長 | 寫死 `4.2s` | 從 `history` 計算平均 `duration_ms`，無資料顯示 `--` |
| L95: 待審批 | 寫死 `2` | 新增 `pendingCount` prop 從 page.tsx 傳入 |
| L103-108: Alert Radar | 4 筆假告警 | 從 `history` 最新 4 筆衍生，或從 `/api/v1/incidents` 取活躍告警 |
| L34-39: CHAIN_NODES | 假鏈路 | 無活躍修復時顯示 idle 狀態，有時從最新 history item 衍生 |

**新增 Props**:
```typescript
interface Props {
  stats: AutoRepairStats | null
  history: RepairHistoryItem[]
  pendingCount: number        // 新增: 從 page.tsx 傳入
  activeIncidents?: any[]     // 新增: 活躍告警 (可選)
}
```

### P0-2: NeuralStats.tsx

**問題**: SCHEME_STATS + PLAYBOOK_RANKINGS + MOCK_HISTORY + 假 KPI
**後端 API**: 已有 `stats` + `playbooks` + `history` props

| 修復項 | 現況 (假) | 修復方案 |
|--------|-----------|----------|
| L20-23: SCHEME_STATS | 寫死 116/34/6 | 從 `history` 聚合計算 scheme 分佈 |
| L26-31: PLAYBOOK_RANKINGS | 寫死 5 個排名 | 從 `playbooks` prop 排序 (success_count/total) |
| L40-46: MOCK_HISTORY | 5 筆假歷史 | 移除，直接用 `history` prop |
| L52: successRate fallback | `?? 0.87` | `?? 0` + 無資料時顯示 `--` |
| L53: totalExec fallback | `?? 156` | `?? 0` |
| L59: 平均時長 | 寫死 `4.2s` | 從 `history` 計算 |
| L60: 待審批 | 寫死 `2` | 新增 prop `pendingCount` |

### P0-3: NeuralApprovalPanel.tsx

**問題**: 整個面板用 MOCK_PENDING 假審批
**後端 API**: `/api/v1/approvals/pending` 已存在

| 修復項 | 現況 (假) | 修復方案 |
|--------|-----------|----------|
| L17-33: MOCK_PENDING | 假審批 APR-2026-0042 | 接收 `approvals` prop (PendingApprovalsResponse) |
| 無 pending 時 | 永遠顯示假審批 | 顯示 "目前無待審批項目" EmptyState |
| 審批動作 | 純前端 state | 呼叫真實 `/api/v1/approvals/{id}/sign` 或 `/reject` |

**新增 Props**:
```typescript
interface Props {
  approvals: ApprovalItem[]    // 從 page.tsx 傳入
  onApprove: (id: string) => Promise<void>
  onReject: (id: string) => Promise<void>
}
```

### P0-4: page.tsx (Neural Command) 修改

page.tsx 已在 fetch 四個 API，但需要:
1. 將 `pendingApprovals` count 和 approvals list 傳給子組件
2. 新增 incidents fetch 給 Alert Radar

---

## Phase P1: 假用戶身份清除

**影響**: 7 處使用 `demo-user` / `user-001` / `Demo User`

| 檔案 | 修復方案 |
|------|----------|
| live-approval-panel.tsx:101-102 | 改用 `AWOOOI_USER_ID` / `AWOOOI_USER_NAME` 環境變數或 constants |
| conversational-view.tsx:65-66 | 同上 |
| batch-mode-selector.tsx:74-75 | 同上 |
| hitl-section.tsx:238,258 | 同上 |
| ai-command-panel.tsx:54,60 | 同上 |

**方案**: 建立 `src/constants/user.ts`:
```typescript
// 統帥是唯一用戶，在多用戶系統實作前使用固定身份
export const CURRENT_USER = {
  id: 'commander',
  name: '統帥',
} as const
```

---

## Phase P2: Demo 組件清理

| 檔案 | 動作 |
|------|------|
| charts/global-pulse-chart.tsx:190-223 | 刪除 `GlobalPulseChartDemo` |
| charts/ai-process-stepper.tsx:236-273 | 刪除 `AIProcessStepperDemo` |
| charts/index.ts:8-9 | 移除 Demo 匯出 |
| approval/index.ts:32-98 | 刪除 `MOCK_APPROVAL_*` 三個常數 |
| incident/thinking-terminal.tsx:359-387 | 刪除 `DEMO_DECISION_CHAIN` |
| incident/index.ts:8 | 移除匯出 |

**前提確認**: 搜尋確認這些 export 沒有被任何生產頁面 import。

---

## Phase P3: Demo 頁面

| 動作 | 說明 |
|------|------|
| 保留但加保護 | `/demo` 路由加 `NEXT_PUBLIC_ENABLE_DEMO=true` 環境變數保護 |

**理由**: Demo 頁面用於內部測試 (LiveDashboard + HITLSection 都接真實 API)，但不應在生產暴露。

---

## 實施順序 (無衝突)

```
P0-4 (page.tsx 增加 props 傳遞)
  ↓
P0-1 (NeuralLiveCenter) ─── 可平行 ──→ P0-2 (NeuralStats)
  ↓
P0-3 (NeuralApprovalPanel)
  ↓
P1 (假用戶身份)
  ↓
P2 (Demo 組件清理)
  ↓
P3 (Demo 頁面保護)
  ↓
驗證 + 文件更新
```

**P0-1 和 P0-2 可平行** (無依賴)，P0-3 需要 P0-4 先完成 (approvals prop)。

---

## 驗證清單

- [ ] `npm run build` 通過 (無 TypeScript 錯誤)
- [ ] Neural Command 頁面四個 Tab 正常渲染
- [ ] 無資料時顯示 `--` 或 EmptyState (非假數據)
- [ ] 有真實資料時正確顯示
- [ ] 審批操作呼叫真實 API
- [ ] 全域搜尋 `MOCK_` / `DEMO_` / `demo-user` 零殘留
- [ ] `grep -r "136/156\|0\.87\|4\.2s" apps/web/src/` 零殘留
