# Architect 交叉審閱 — PRD 與設計規格 | 項目 | 內容 | |------|------| | 審閱者 | Architect Agent(交叉審閱實例) | | 範圍 | `02-prd/*` + `03-design/*` | | 審閱日期 | 2026-04-21 | | 架構基準 | 雙 binary(api-server + remote-proxy),沿用 POC tunnel / yamux,無 Redis、無 DB、StaticAuthService | --- ## 1. 總評 | 面向 | 評分(5 級) | 說明 | |------|------------|------| | 需求與架構整體對齊 | **4** | PRD 的 P0 功能都與雙 binary 架構匹配;few gaps 需標示 | | 技術可行性 | **4** | 核心 P0(登入 stub、Pairing、裝置列表、Camera 推論)都能在雛形範圍達成 | | 效能 NFR 合理性 | **3** | 端到端推論 P95 < 500ms 偏樂觀;Tunnel 建立 < 2s、重連 < 5s 可達 | | 隱藏依賴揭露 | **3** | 有若干設計項目預設後端能力未於 TDD 落地(見第 4 節) | **整體結論**:**可進入雛形實作**,但 5 個 Major 與若干 Minor 需在建雛形前確認或調整。 --- ## 2. P0 / 核心頁面可行性逐項檢查 | 項目 | 來源 | 可行性 | 備註 | |------|------|--------|------| | US-01/02/13 登入 / 註冊 / 登出 stub | PRD | **可行** | StaticAuthService 回 demo-user,前端 form submit 後直跳 | | US-03 裝置列表 | PRD + `pages.md §5` | **可行** | in-memory SessionStore 查詢即可 | | US-04 取 Pairing Token | `feature-pairing.md` | **可行** | api-server 產生,存 in-memory map | | US-05 local agent 用 token 建 tunnel | `feature-pairing.md` | **可行但有風險** | 雛形用 POC `edge-ai-server` 當 tunnel client(Q3 決策);需驗證 token 驗證路徑 | | US-06 即時更新裝置列表 | `feature-pairing.md` | **可行** | 設計走 WebSocket 廣播;雛形也可退化為 3-5 秒 polling(見 Major #2)| | US-07 裝置詳細 | `feature-device-management.md` | **可行** | 透過 tunnel 轉發到 agent | | US-08/09 模型 7 預設 + 上傳 | `feature-model-management.md` | **可行** | LocalFSStorage 實作 ObjectStorage 介面 | | US-10/11 Camera 推論 + MJPEG | `feature-inference.md` | **可行但需驗證** | MJPEG binary + yamux 吞吐量需 PoC 驗證(見 Major #3)| | US-12 i18n + Dark Mode | PRD | **可行** | 沿用 local-tool | | `/devices/pair` Stepper | `flow-pairing.md` | **可行** | 三步驟流程無技術難點 | | `/clusters`(從 POC 搬)| `pages.md §9` | **P1 / 非 P0**,可行 | 本次雛形不進 P0 | | 離線降級遮罩 / Banner | `flow-offline-handling.md` | **可行** | 需後端提供 heartbeat 與狀態推送 | --- ## 3. 效能與 NFR 風險 | 指標 | PRD 目標 | Architect 評估 | 風險等級 | |------|---------|--------------|---------| | Camera 端到端延遲 P95 | < 500ms | 本機 150-250ms + WAN RTT 50-200ms + 雲端 proxy 5-10ms + 渲染 10-50ms,**實測可能 400-550ms**;雛形內網測試能過,WAN 場景要驗證 | 🟡 中 | | Tunnel 建立 < 2 秒 | Phase 0 目標 | TLS handshake + yamux handshake + token 驗證,若冷啟動可能到 2-3 秒 | 🟢 低 | | Tunnel 重連 < 5 秒 | Phase 0 目標 | 指數退避第一次重連 1s 內可達,**需注意退避演算法不要過保守** | 🟢 低 | | Tunnel throughput ≥ 5 Mbps | Phase 0 | yamux 單 stream 足以;MJPEG 480p ~2-5 Mbps,**臨界值需實測** | 🟡 中 | | 並發 yamux streams ≥ 32 | Phase 0 | POC 已驗證,可沿用 | 🟢 低 | | API 簡單端點 P95 < 200ms | Phase 0 | in-memory 查詢 + 小邏輯,輕鬆達標 | 🟢 低 | | 多 tab 同看同一推論 | `feature-inference.md` 驗收 | MJPEG multipart 多 consumer + WebSocket 廣播,**需確認 remote-proxy fan-out 行為**(Q5 決策是覆蓋,不是 fan-out)| 🔴 高(見 Major #4)| --- ## 4. 發現的問題(按嚴重度) ### 🔴 Critical — 0 項 _無阻擋雛形上路的問題。_ ### 🟠 Major — 5 項 **M1.「裝置自動出現在雲端頁面」的即時推送機制未明確**(PRD US-06、`feature-device-management.md §即時事件`) - PRD 預設走 WebSocket 廣播(`/ws/devices/events`),Design 的離線處理也依賴 WebSocket push - 但 Q5 裁決「同 token 後連覆蓋前連」、Q1 決策「不引入 Redis」,**沒有跨 api-server instance 的 pub/sub** - 雛形單機可走 process-internal event bus;**但這限制必須寫進 TDD**,避免後續誤開第二個 api-server instance 時事件廣播失效 - **建議**:TDD 明定「雛形單 api-server instance;多 instance 擴展留 Phase 1」,並在 Design Doc 加 Non-Goals **M2.「Pairing Token 有效期」PRD 與 Design 不一致** - `feature-pairing.md` 寫 **TTL 15 分鐘** - `flow-pairing.md` §4.1 顯示 **「有效期:72 小時」**,§7.1 也寫 72 小時 - 兩個數字差了一個數量級,**必須裁決** - **建議**:Phase 0 雛形採 **15 分鐘**(PRD 為準,安全性較好);如 UX 認為 15 分鐘太短,改 1-2 小時比 72 小時更合理 **M3. MJPEG binary stream 過 yamux 的吞吐量未驗證**(`feature-inference.md` §4) - 設計預設 MJPEG 480p(~2-5 Mbps)能透過 yamux 單 stream 穩定傳輸 - POC 驗證的是低頻控制訊息,**未必涵蓋 sustained binary stream** - **建議**:雛形實作前先做 1 天的 PoC — 用 POC 的 tunnel 跑 5 分鐘 MJPEG,量測 throughput / drop rate - 若不達標,退路是降 MJPEG 解析度到 360p 或改 H.264 **M4. 多 tab 同看同一推論的 fan-out 設計**(`feature-inference.md` 驗收條件) - 驗收條件要求「同一使用者開兩個 tab 看同一裝置推論 → 都能看」 - 但 Q5 決策是「同 token 後連覆蓋前連」,**這是在 tunnel 層**,不等於 MJPEG stream 層 - 目前設計未描述:同一個從 agent 來的 MJPEG stream,api-server 要 fan-out 給 N 個瀏覽器 client - **建議**:雛形可以限制「一個裝置同時只能被一個 tab 開推論」,把 multi-tab 驗收條件降級為 P1;若要 P0 支援,TDD 必須加 stream multiplexer 設計 **M5. 設計預設後端回傳 `lastSeenAt`、`remoteStatus`、`hostName` 等欄位,但 API spec 未必齊** - `flow-offline-handling.md §2` 定義 Device 介面新增欄位 - `design-spec.md §5.2` 已提醒 Architect,但 TDD 要確實補上 - **建議**:TDD 的 `/api/devices` response schema 明確包含:`remoteStatus`、`lastSeenAt`、`hostName`、`pairedAt`、`errorMessage` ### 🟡 Minor — 4 項 **m1. Pairing Token 長度 / 字首規範兩份文件寫法不一** - `feature-pairing.md` 規範 `vAc_` 字首 + 32 hex - `flow-pairing.md` / `wf-pairing.md` 範例顯示 **16 字元 hex 無字首**(`a1b2c3d4e5f6g7h8`) - 健檢也確認「POC 是 16 字元 hex」 - **建議**:Phase 0 先用 16 字元 hex 與 POC 一致,`vAc_` 字首留 Phase 1 **m2. 「連線品質圖表」、「Latency 顯示」 design 標 Phase 1,但 `design-spec.md §5.1` 提到 Tunnel 延遲在雲端版是 P0 顯示** - 對齊一下:Phase 0 顯示「單次 RTT 數字」即可;「歷史圖表」Phase 1 - 雛形 agent heartbeat 回傳 timestamp,api-server 計算 now - lastSeenAt 即得 RTT 近似值 **m3. Storage 介面的 `GetUploadURL` / `GetDownloadURL` 在 LocalFSStorage 該如何實作未明** - `feature-model-management.md §ObjectStorage 介面` 包含這兩個方法 - LocalFSStorage 雛形應該:`GetDownloadURL` 回傳 `/api/models/{id}/download` 走 api-server 串流;`GetUploadURL` 雛形可回 `error: not supported`(前端 fallback 到 multipart form upload) - **建議**:TDD 裡明寫這個回退行為 **m4. `/workspace/[deviceId]` 掉線時「保留最後一幀」的實作位置** - `flow-offline-handling.md §6.2` 要求 Camera stream 顯示最後一幀 + overlay「連線中斷」 - 實作上是前端 canvas 緩存,還是後端保留? - **建議**:前端 canvas 自己緩存 last frame;後端不需額外邏輯(省事) ### 🟢 Suggestion — 2 項 **s1. PRD Phase 0 SLO(api-server 95%、remote-proxy 99%)對單人開發雛形過嚴** - 建議 Phase 0 直接標「SLO N/A — 內部驗證階段」,避免造成「要做 HA 才能達標」的錯覺 **s2. 「5 秒內裝置上線反映」(`feature-device-management.md` 驗收條件)對照 Q5「覆蓋前連」的決策** - 覆蓋瞬間新 session 建立 → event bus 推播 → 前端更新,實測通常 < 2 秒 - 可寫進 TDD 測試清單作為雛形驗收指標 --- ## 5. 建議的下一步 1. **使用者裁決 M2**(Pairing Token TTL:15 分鐘 vs 72 小時) 2. **Architect TDD 補強 M5**(Device API schema 明定 `remoteStatus` / `lastSeenAt` / `hostName`) 3. **Architect TDD 寫入 Non-Goal:單 api-server instance / 不跨節點事件廣播**(M1) 4. **雛形前置 PoC**:跑一次 MJPEG over yamux 吞吐量測試(M3),1 天內可完成 5. **驗收條件降級**:multi-tab 同看推論 → 改 P1(M4) --- ## 6. 整體判斷 PRD 與設計規格**結構完整、彼此呼應度高**(Design Agent 已主動標註給 Architect 的提醒)。技術可行性上沒有阻擋雛形的問題,但有 **5 個 Major** 屬於「不處理會在實作時踩雷」的層級,建議在雛形骨架建立前用 1-2 天處理完成。