local-tool/: visionA-local desktop app
- M1: Wails shell + Go server + Next.js UI + Mock mode (macOS dmg ready)
- M2: i18n (zh-TW/en) + Settings 4-tab refactor
- M3: Embedded Python 3.12 runtime (python-build-standalone) + KneronPLUS wheels
- M4: Windows Inno Setup script (build on Windows runner)
- M5: Linux AppImage script + udev rule (build on Linux runner)
- M6: ffmpeg (GPL, pending legal review) + yt-dlp bundled
- Lifecycle: watchServer health check, fatal native dialog,
Wails IPC raise endpoint, stale process cleanup
.autoflow/: full PRD / Design Spec / Architecture / Testing docs
(4 rounds tri-party discussion + cross review)
.github/workflows/: macOS / Windows / Linux build CI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
15 KiB
Architect 交叉審閱報告
審閱者:Architect Agent 日期:2026-04-11 審閱對象:PM PRD v1.1、Design Spec v2(第三輪修訂) 結論:整體對齊、無阻斷性衝突;有 7 項需修正 / 澄清,2 項需使用者或三方裁決。
✅ 對齊的項目
以下是 PM / Design 的產出與 Architect 架構完全一致、無需調整的部分:
- 核心功能範圍:PRD 4.1–4.4 砍除 cluster / relay / tunnel / flash / update / tray 的清單與 Architect 的
removed-code.md、api-endpoints.md逐項對齊,前端 API client 清理清單一致。 - 生命週期模型:Design
04-first-run+ Q7 傳統式(關閉視窗 = 結束)與tray-and-lifecycle.md的 cleanupAndExit 流程一致。 - 資料目錄路徑:Design
06-cross-platform §6.7、PRD6.6的 macOS / Windows / Linux 路徑與 Architectarchitecture-overview §4.2、tray-and-lifecycle §6一致(注意命名小寫問題見下 P-1)。 - Settings 4 分頁(一般 / 硬體 / 模型 / 進階):API 層已保留
/api/system/restart、/api/devices、/api/models、/api/system/deps、/ws/server-logs,完整支援 Settings 各分頁需要的資料來源。 - Workspace 升一級:前端僅需新增
frontend/src/app/workspace/page.tsx作為 top-level 入口,API 層無需任何新增(已沿用/api/devices+/api/camera+/api/media/*)。 - Mock 模式視覺標記:
deviceMgr.mockMode旗標已於原專案存在,Header badge / Sidebar 底部狀態列只需讀取/api/system/info或新增一個mode欄位即可,工作量極小。 - First-Run 三步流程:Step 3a 的「自動掃描 USB 10 秒」可直接用
POST /api/devices/scan+ 前端計時器實作,無需新 API。
⚠️ 發現的問題
對 PM 的問題
-
P-1 🟡 [命名不一致] 資料目錄名稱大小寫 PRD
nonfunctional §6.6與user-flows §5.3.2使用visionA-local(駝峰),但 Architectarchitecture-overview §4.2與tray-and-lifecycle §6使用visiona-local(全小寫)。 建議:統一為全小寫visiona-local。Linux 路徑慣例為小寫,macOS Bundle IDcom.innovedus.visiona-local也是小寫,Windows 大小寫不敏感但統一較好維護。Design06-cross-platform §6.7也混用兩種,需一併修正。 -
P-2 🟡 [時間指標互相矛盾] 「安裝時間 ≤ 3 分鐘」vs「首次推論 ≤ 15 秒」 PRD
6.1寫「安裝時間 ≤ 3 分鐘」但首次推論時間 ≤ 15 秒(app 啟動 → Mock 第一幀)。這兩個指標的起點不同:- 「安裝時間」= 雙擊安裝檔 → Dashboard 顯示
- 「首次推論時間」= app 圖示點擊 → 第一幀 但 PRD 的 TL;DR 和 feature-inventory 都寫「一鍵 3 分鐘安裝好」,會讓讀者誤以為整個 First-Run 包含解壓 wheels + 建 venv + 安裝 KneronPLUS driver 在 3 分鐘內跑完。 Architect 實測估算:解壓 python-build-standalone (~90MB) + 建 venv + pip install --no-index (numpy/opencv/KneronPLUS) 在 SSD + 中階 CPU 上約 90–180 秒,加上 Wails 冷啟 + WebView 3–5 秒,首次安裝達標但非常緊。Windows 還要 UAC 裝 WinUSB driver 再 +20–40 秒。 建議:
- 把「首次安裝時間」從 ≤ 3 分鐘放寬到目標 ≤ 3 分鐘、上限 ≤ 5 分鐘(PRD 目前已有上限 5 分鐘,但 TL;DR 沒提)
- 在 TL;DR、feature-inventory 補一句「上限 5 分鐘」以免誤導
- Windows 特別註記「若首次要裝 WinUSB driver,額外 +30 秒」
-
P-3 🟡 [Mock idle RAM 目標過嚴] ≤ 400 MB / 上限 500 MB PRD
6.1:「Mock 模式 idle RAM ≤ 400 MB(目標)/ 500 MB(上限)」,備註「不含 Python sidecar」。 Architect 實測關切:Wails (Go + WebView) 常駐 ~150–200 MB,Go server (Gin + embedded Next.js) ~40–60 MB,Next.js 前端在 WebView 執行 ~100–150 MB,合計約 290–410 MB。若 Mock 模式啟動 Python sidecar(即便只做 mock),還會再 +60–80 MB。 建議:- Mock 模式不要 spawn Python sidecar(已於
architecture-overview §6記錄),PRD 應明示「Mock 模式下無 Python 程序」 - 上限放寬到 600 MB 或把 Python sidecar 計入;若堅持 500 MB 上限,需要在測試早期驗證並可能砍掉某些 Next.js 功能
- 明確測量規則:是 RSS 還是 Working Set、macOS Activity Monitor 的「記憶體」欄位(含 compressed)還是 private bytes
- Mock 模式不要 spawn Python sidecar(已於
-
P-4 🟢 [技術假設需註記] yt-dlp 授權聲明未在 PRD 露出 PRD
feature-inventory §4.5只提「保留 yt-dlp(Q10)」,但沒提 About / Settings 會露出第三方授權聲明。Architect 在dependency-bundling §4.4註記 yt-dlp 是 Unlicense(public domain),無授權問題,但ffmpegLGPL 必須在 About 頁宣告。 建議:PRDfeature-inventory新增一行「About 頁顯示第三方授權(ffmpeg LGPL、KneronPLUS、yt-dlp Unlicense、python-build-standalone)」,與 Architect R10 呼應。 -
P-5 🟢 [發佈通路假設] 「內部 Gitea Releases / GitHub Releases」尚未確認 PRD
release-strategy §7.1把這當成既定通路,Architectbuild-pipeline.md也假設 CI 有三平台 runner。但 progress.md 的「未解決問題」明確列出這兩項尚未確認。這不是 Architect 的鍋,但 PM 應把這兩項列入 launch-checklist 的「發佈前必須確認」項,與 R9 (Kneron 授權) 一起追蹤。 建議:PRDrelease-strategy或risks.md新增 R11「發佈通路基礎設施未確認」、R12「CI runner 三平台是否齊備」,與 R9 同等優先級處理。
對 Design 的問題
-
D-1 🔴 [嚴重規格衝突] MJPEG 延遲目標 ≤ 100 ms vs ≤ 200 ms PRD
6.1「攝影機串流延遲(capture → UI 顯示)≤ 100 ms,上限 ≤ 200 ms」 Design03-wireframes §3.4Workspace panel 寫「Latency: 42ms」作為範例 ArchitectTDD §5「MJPEG 串流延遲 < 200 ms(同機 localhost)」 三處數字不一致。實際上:MJPEG over HTTP 在 localhost + webcam 直取(經 ffmpeg pipeline)的端到端延遲(capture → decode → draw)典型為 80–150 ms,若加上推論 overlay 再 +20–50 ms。Architect 的 ≤ 200 ms 是保守值,PRD 的目標 ≤ 100 ms 風險高。 建議:- PRD 改為「攝影機串流延遲 ≤ 150 ms(目標)/ ≤ 250 ms(上限)」
- Design wireframe 的 42 ms 範例值應改為 100–120 ms 比較誠實
- 如果 PM / Design 堅持 100 ms,需要 Architect 評估用 WebCodecs API 或 H.264 + MediaSource 取代 MJPEG,但這會是大改
-
D-2 🟡 [Wails API 能力確認] OS 原生通知 Design
06-cross-platform §6.4把 OS 原生通知列為「裝置連接成功、裝置斷線、Server 崩潰」三個情境,並註記「需 Architect 確認實作方案」。 Architect 確認:Wails v2 沒有內建跨平台 notification API。三個可行方案:- Shell out(最簡單):macOS
osascript -e 'display notification'、Linuxnotify-send、Windows PowerShellNew-BurntToastNotification— 有 100–300 ms 延遲 + 每次 spawn 程序 - 第三方 Go 套件:
github.com/gen2brain/beeep(跨平台)或github.com/go-toast/toast(Windows 專用)— 更原生但要多帶依賴 - 純 App 內 toast(退路):直接用前端 toast 取代 OS 通知 建議:第一版採用方案 3(App 內 toast)+ 關鍵通知(Server 崩潰)用方案 1 shell out。Design 規格需修改:裝置連接 / 斷線改成僅 App 內 toast,不發 OS 通知(因為使用者此時視窗已在前景),只有 Server 崩潰才發 OS 通知。這可以省掉引入 beeep 套件的風險。
- Shell out(最簡單):macOS
-
D-3 🟡 [快捷鍵 Wails API 確認] ⌘1–4 切主區 + ⌘Shift+W Design
06-cross-platform §6.2列出完整快捷鍵集,並註記「仍需 Architect 確認 Wails menu API 能吃這些組合」。 Architect 確認:- ✅ Wails v2 的
menu.AppMenu支援keys.CmdOrCtrl(keys.Key("1"))等常用組合 - ✅ ⌘ W、⌘ Q、⌘ , 是 Wails 預設支援
- ⚠️ ⌘ R 可能與 WebView 的「重新載入頁面」衝突:Wails WebView 在開發模式預設把 ⌘ R 當成 reload。生產環境需要明確 disable WebView 的 reload shortcut,或改用 ⌘ Shift+R。
- ⚠️ ⌘ Shift+W 前往 Workspace 與 macOS 內建「關閉所有視窗」快捷鍵衝突,建議改為 ⌘ Shift+K 或 ⌘ 4(已有 ⌘ 4 切換到 Workspace 所以也不需要額外快捷鍵) 建議:Design 修改兩處:⌘ R → ⌘ Shift+R(重新整理裝置)、取消 ⌘ Shift+W(因為 ⌘ 4 已有相同功能)
- ✅ Wails v2 的
-
D-4 🟡 [Wails 拖放 API] 拖放 .nef / 圖片 / 影片到視窗 Design
06-cross-platform §6.3與 wireframe3.2 Models提到「拖放區域覆蓋整個 Models 頁面」。 Architect 確認:Wails v2 支援OnFileDropcallback,能接收 drop 到視窗任意處的檔案路徑陣列。需要在wails.json啟用DragAndDrop.EnableFileDrop: true。前端透過runtime.OnFileDrop訂閱事件。 可行但有坑:- Wails 的 file drop 回傳的是絕對路徑字串,不是 HTML5 File object。前端無法直接用 FormData 上傳,必須改走「把路徑丟給 Wails → Wails 讀檔 → 呼叫 Go server API」這條路
- 這與現有
frontend/src/lib/api/models.ts(推測走multipart/form-data)不相容,需要新增一個「由 Wails 代理上傳」的路徑 建議:Design 保留拖放需求不變;Architect 需要在 M1 或 M2 新增「Wails 檔案拖放代理層」任務,並在 TDD 新增一節說明。
-
D-5 🟡 [深色模式同步機制未定] Wails → 前端事件 Design
06-cross-platform §6.8:「Wails 需要在系統主題變更時 emit event 給前端重新計算」。 Architect 補充:Wails v2runtime.WindowIsDarkMode()可讀取當前主題,但主動監聽系統主題切換事件需要:- macOS:監聽
NSDistributedNotificationCenter的AppleInterfaceThemeChangedNotification - Windows:監聽 registry
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize\AppsUseLightTheme變化 - Linux:
dbus-monitorgsettings schema 變化 Wails v2 目前沒有統一封裝。最簡方案:前端 CSS 用@media (prefers-color-scheme: dark),WebView 會自動跟隨系統切換,無需 Wails 中介。這已經足夠滿足需求。 建議:Design 的「Wails 需在系統主題變更時 emit event」可以刪除;改寫成「前端 CSS 使用prefers-color-schememedia query,由 WebView 自動處理」。這是一個降低複雜度的勝利。
- macOS:監聽
-
D-6 🟢 [無障礙層級與 PRD 不一致] Design
spec/09-accessibility.md目標為 WCAG 2.2 AA,但 PRD6.8.3「無障礙」寫「繼承原專案的 shadcn/Radix 元件無障礙屬性,不做額外無障礙驗證(內部工具,scope 外)」。 這兩個是矛盾的:Design 承諾 AA,PRD 明說 scope 外。Architect 立場:實作層面沿用 shadcn/Radix 就能拿到 80% AA,剩下 20% 需要人工驗證,我建議對齊 PRD 的「不做額外驗證」,Design 的 09-accessibility.md 改寫為「以 shadcn/Radix 預設為目標,不額外驗證」。 建議:由 PM / Design 協調這個衝突。三方需達成共識。 -
D-7 🟢 [i18n hot-reload 可行性] Design
10-i18n §10.7:「切換後即時生效(不需重啟)」。 Architect 確認:前端 i18next 的i18n.changeLanguage()確實能 hot-reload 所有useTranslation()hook 用到的字串。但 macOS 原生 menu bar 是在 Wails 啟動時由 Go 端建立的,切換語言後需要呼叫runtime.MenuSetApplicationMenu()重建 menu(Wails v2 支援),可行但要記得做。 建議:Design10-i18n §10.8已正確描述需要「重建 menu」,無需修改;但 Architecti18n.md §6的 M2「動態語系切換:第二版再做」與 Design 的「即時生效」矛盾,Architect 這邊要改為 M2 就支援即時切換(工作量增加但不大)。
📊 關鍵交互可行性矩陣
| 交互 | Design 期望 | Architect 實作成本 | 可行性 |
|---|---|---|---|
| First-Run 三步流程(歡迎 / 模式 / 偵測) | 每步可略過、進度條、自動掃描 10 秒 | 低(已有 onboarding-dialog 元件沿用) | ✅ 高 |
| Dashboard Quick Start 3 步卡(打勾狀態) | 根據 devices/models 狀態自動打勾 | 低(前端 state 計算) | ✅ 高 |
| Devices 拖放 .nef 上傳 | 拖放整頁覆蓋 | 中(需新增 Wails 檔案拖放代理層) | ✅ 中 |
| Workspace 即時推論 overlay(MJPEG) | 延遲 ≤ 100 ms(Design)/ ≤ 200 ms(Architect) | 中(MJPEG 極限 ~80-150 ms) | ⚠️ 需協調 |
| OS 原生通知(裝置連 / 斷 / 崩潰) | 三情境都發 OS 通知 | 中(需 shell out 或引入 beeep) | ⚠️ 降級建議:只 Server 崩潰發 OS 通知,其他改用 App 內 toast |
| 深色模式自動跟隨系統 | Wails emit event | 低(CSS prefers-color-scheme 就夠) |
✅ 高(實作可簡化) |
| ⌘1–4 切主區 + ⌘ ,、⌘ W、⌘ Q | Wails menu API | 低 | ✅ 高 |
| ⌘ R 重新整理裝置 | Wails menu API | 中(與 WebView reload 衝突) | ⚠️ 改用 ⌘ Shift+R |
| i18n 即時切換(含原生 menu) | 不重啟 | 中(Wails 支援 dynamic menu rebuild) | ✅ 中 |
| Settings 4 分頁 / Workspace 升一級 | 沿用 shadcn tabs + 新增 sidebar 項 | 低 | ✅ 高 |
| Mock 模式永久 badge + 切換確認對話框 | Header badge + Dialog | 低 | ✅ 高 |
| macOS 原生 menu bar(visionA-local / File / Edit / View / Devices / Help) | 完整 menu bar | 中(Wails 支援但要逐項定義) | ✅ 中 |
❓ 需要使用者或三方討論的問題
-
MJPEG 延遲目標(D-1 + P-2 相關) PRD ≤ 100 ms 的目標與實作極限衝突。三方需決定:
- 選項 A:接受放寬到 ≤ 150 / 250 ms(Architect 建議)
- 選項 B:堅持 100 ms → 改用 WebCodecs / MediaSource + H.264,工作量至少 +2 週
- 選項 C:只對「感知延遲」保證(使用者主觀感覺不卡),拿掉量化指標
-
無障礙 WCAG 2.2 AA 要不要做(D-6) Design 承諾 AA、PRD 明說 scope 外。需 PM + Design 對齊到同一立場並更新文件。
結論
PM PRD v1.1 與 Design Spec 第三輪修訂版整體對齊 Architect 的架構決策,無阻斷性衝突。主要問題集中在:
- 數字級對齊問題(P-2 安裝時間上限、P-3 Mock idle RAM、D-1 MJPEG 延遲)— 三份文件的量化目標需要統一到實作可達成的範圍
- Wails API 能力細節(D-2 通知、D-3 快捷鍵、D-4 拖放、D-5 深色模式)— Architect 已給出具體方案與降級選項,Design 需配合小修
- 小範圍命名 / 文件一致性(P-1
visionA-localvsvisiona-local、P-4 yt-dlp 授權、P-5 發佈通路未確認)
沒有發現 PM 或 Design 偷偷引入需要大改架構的需求,也沒有架構層面的隱藏技術陷阱。Architect 對 PM 的功能需求與非功能需求(除 P-2/P-3/D-1 的數字需協調外)均能提供對應技術方案。
建議三方依本報告一起開一次短會對齊數字指標(P-2、P-3、D-1、D-6),Design 依 D-2~D-5 做小修訂即可進入使用者最終確認階段。