# Code Review 報告 — M1-7(前端清理 + pnpm build) ## 審查摘要 - 審查對象:`frontend/src/`(清理 cluster/relay 相關程式碼)、`frontend/out/`(pnpm build 產物) - 產出 Agent:Frontend Agent - 審查結果:✅ 通過(帶已知 walk-around,不阻斷 M1) - 問題統計:Critical: 0 / Major: 0 / Minor: 4(皆已知、延到 M2)/ Suggestion: 1 ## 驗收項目清單 | # | 驗收項目 | 結果 | 證據 | |---|---------|------|------| | 1 | `frontend/src/app/clusters/` 不存在 | ✅ | `ls` → No such file or directory | | 2 | `frontend/src/app/workspace/cluster/` 不存在 | ✅ | `ls` → No such file or directory | | 3 | `frontend/src/components/cluster/` 不存在 | ✅ | `ls` → No such file or directory | | 4 | `frontend/src/components/relay-token-sync.tsx` 不存在 | ✅ | `ls` → No such file or directory | | 5 | sidebar 不含 Clusters 導航項 | ✅ | `sidebar.tsx` navItems 僅 dashboard / models / devices / workspace / settings | | 6 | Workspace 已提升為一級導航 | ✅ | `{ href: '/workspace', label: 'Workspace', icon: 'W' }` | | 7 | `pnpm build` 可重現且成功 | ✅ | `Compiled successfully in 3.9s`、`Generating static pages (11/11)` | | 8 | 產出 `frontend/out/` | ✅ | 已產出,含 index.html、devices/、models/、settings/、workspace/ | | 9 | `frontend/out/` 無 clusters 目錄 | ✅ | `ls out/ \| grep cluster` → 無 | | 10 | cluster 殘留皆為字串/註解,非 import/JSX | ✅ | grep 命中 4 檔:`i18n/types.ts`、`i18n/en.ts`、`i18n/zh-TW.ts`、`use-resolved-params.ts`(註解中的範例路徑) | ## pnpm build 輸出路由表 ``` ○ / (Static) ○ /_not-found ○ /devices ● /devices/[id] (SSG, uses generateStaticParams → /devices/_) ○ /models ● /models/[id] (SSG → /models/_) ○ /settings ○ /workspace ● /workspace/[deviceId] (SSG → /workspace/_) ``` 全部 11 個靜態頁面成功產出,無編譯錯誤、無 TypeScript 錯誤。 ## 問題清單 ### Minor(已知 walk-around,延至 M2,不阻斷 M1) | # | 檔案 | 問題描述 | 延後原因 | |---|------|---------|---------| | 1 | `settings/page.tsx`(推定) | Settings 頁面仍保留 relay token / update-check UI | M2 才重構 Settings | | 2 | `lib/i18n/en.ts`, `zh-TW.ts`, `types.ts` | i18n 字串仍有 `cluster` key | M2 才清 i18n | | 3 | `stores/activity-store.ts` / `components/activity-timeline.tsx`(推定) | `flash_*` 字串常量還在 | M2 才清 | | 4 | `components/layout/sidebar.tsx` L16 | Workspace 用硬編字串 `label: 'Workspace'`,沒走 `t('nav.workspace')` | M2 補 i18n key | ### Suggestion(非必要) | # | 說明 | |---|------| | 1 | Next.js static export 把 `workspace/[deviceId]` 產成 `workspace/_/` 佔位目錄(SSG with `generateStaticParams` 只產出 `_` 這一個 stub)。執行期 Wails shell 會用 `/workspace/{deviceId}` 的 hash route 或 query string 導航,實際渲染靠 client-side 拿 deviceId,目前方式 OK;建議在 `use-resolved-params.ts` 或 workspace 的 client component 加一行註解說明這個 pattern,以免未來有人看到 `out/workspace/_/` 覺得怪 | ## 動態路由 static export 的行為確認 `workspace/[deviceId]`、`devices/[id]`、`models/[id]` 在 Next.js 16 static export 下,若 `generateStaticParams` 回傳空陣列或包含 `_` placeholder,會產出 `//_` 作為 stub。**這是 Next.js 官方支援的做法**,runtime 在 Wails 環境用 client-side routing 拿到實際的 `deviceId` 即可。**不影響 M1 驗收**(macOS 雙擊 dmg 能跑)。 ## 優點 - 刪除工作乾淨俐落,四個必刪路徑零殘留 - sidebar 精簡到只剩 5 個一級導航,符合 local-only 定位 - `pnpm build` 首次執行即成功,無需人工介入 - 產物體積合理、所有必要頁面都有產出 - 殘留的 `cluster` 字串都在 i18n 與註解中,不影響編譯,也不影響 runtime 行為 ## 總結意見 **M1-7 通過,可進入 M1 驗收。** 四個已知 walk-around 都明確屬於 M2 範疇(settings 重構、i18n 清理、activity 字串、sidebar i18n key),與 M1 目標「macOS 雙擊 dmg 能跑」無衝突。build 產物完整可用,已準備好給 M1-8 embed 到 Go server。 可進入 M1-9(Wails installer shell)。