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>
14 KiB
Design 交叉審閱報告
審閱者:Design Agent|日期:2026-04-11(第三輪文件完成後) 審閱對象:PM PRD(
02-prd/)、Architect TDD + Design Doc(04-architecture/) 立場:從 UX 角度檢視產品需求與技術方案是否會衝擊使用者體驗
✅ 對齊的項目
- 三方都確認砍掉 tray:PRD §3 非目標、TDD §8(
tray-and-lifecycle.md)、Design §5 一致。 - macOS 資料目錄統一為
~/Library/Application Support/visiona-local/(Q-E1):PRDuser-flows.md、Architectarchitecture-overview.md §4.2、Design04-first-run.md §4.1路徑一致。 - Workspace 升 sidebar 一級(Q-E2):PRD feature-inventory、Design IA、Architect code-reuse-plan 三處都標註。
- Mock 模式預設關閉、需明確選擇:PRD AC-2.1、Design
04-first-run.md §4.4、ArchitectdeviceMgr.mockModeflag 一致。 - Settings 4 分頁結構(Q-E3):PRD、Design 一致採「一般/硬體/模型/進階」。
- 首次啟動體驗可跳過:PRD
user-flows.md §5.2、Design04-first-run.md §4.2都明確三步皆可略過。
⚠️ 發現的問題
對 PM 的問題
-
D→PM-01 [🟡] 「首次推論 ≤ 15 秒」的 AC 與 First-Run 三步流程衝突。 PRD
nonfunctional.md §6.1的驗收值寫「app 啟動 → Mock 第一幀 ≤ 15 秒」,但 Design04-first-run.md的首次流程是歡迎 → 模式選擇 → 硬體偵測(真實模式時要掃 10 秒),在真實模式下光硬體掃描 timeout 就 10 秒,不可能 15 秒到第一幀。建議:把 AC 拆成「首次(含 First-Run)≤ 30 秒」與「回訪(跳過 First-Run)≤ 15 秒」兩個指標,否則測試會一律 fail。 -
D→PM-02 [🟡]
user-flows.md §5.3.1步驟 3「啟動 Go server < 2 秒」與 TDDtray-and-lifecycle.md §4.1的waitHealthy(10s)不一致。 PM 寫「< 2 秒」,Architect 給自己留了 10 秒 timeout。Design 需要知道真實值才能決定 First-Run 是否要插 skeleton/splash。建議 PM 與 Architect 對齊,Design 才能設計正確的 loading 體驗。 -
D→PM-03 [🟢] Error flow
5.4.1Port 3721 被佔用的文案與 Architect 不符。 PRD 寫「請關閉占用該埠的程式,或在 Settings 變更 port」,但 TDDtray-and-lifecycle.md §3.2的pickPort()會自動挑 3722、3723...,根本不需要使用者介入。兩邊敘述衝突,Design08-states.md我暫時沿用 PRD 版,但若採 Architect 自動挑 port,應改成 info toast「已改用 port 3722」。 -
D→PM-04 [🟢]
nonfunctional.md §6.8.3寫「不做額外無障礙驗證」,與 Design09-accessibility.mdWCAG 2.2 AA 承諾衝突。 Design 規格第三輪明確寫 WCAG 2.2 AA、鍵盤 tab 順序、ARIA label。建議 PRD 在非功能需求同步把 a11y 拉到「必達」等級,或 Design 降級;兩邊必須一致。 -
D→PM-05 [🟢] Non-goals 文字微矛盾。 PRD
feature-inventory.md寫「原生 menu bar(File → New Device / Upload Model)」,但vision-and-non-goals.md暗示「不做 quick action」。menu bar 其實就是 quick action 的一種,建議 PM 把「不做 tray」與「有 menu bar」的界線在 non-goals 裡寫清楚,避免未來有人誤解成「連 menu bar 都不能做」。
對 Architect 的問題
-
D→Arch-01 [🔴] 完整冷啟時間沒有明確預算,影響 First-Run AC。 Architect
TDD.md §5只寫「冷啟 < 5 秒」,但三層程序(Wails → Go server → 首次 scan 才 spawn Python sidecar)的疊加時間沒拆開。Design 需要知道:- Wails WebView 載入 Next.js:? 秒
- Go server
waitHealthy:最多 10 秒 - Python sidecar 首次 spawn + KneronPLUS import:? 秒(實測一下,KneronPLUS 通常要 2-3 秒)
若總和超過 5 秒,Design
04-first-run.md §4.5 Phase 1的「掃描 USB 進度條」需要改成「準備硬體子系統中...」以免使用者誤以為 USB 掃描很慢。請 Architect 在 M1 後補上實測數字。 -
D→Arch-02 [🔴] Port picking 導致使用者書籤/歷史的 URL 不穩。
tray-and-lifecycle.md §3.2決定「3721 被佔 → 往上挑 3722、3723」,但 WebView 是http://127.0.0.1:{port}/。使用者不會直接開瀏覽器書籤 localhost(Wails 殼包住 WebView),這對一般使用者 OK,但對「進階使用者想用 Chrome DevTools 連」「Settings 要顯示實際 port」的情境要設計出口。 Design 建議:在 Settings > 進階新增唯讀欄位「目前 Server Port:3722」+「複製」按鈕;Dashboard Server Status 卡片也顯示實際 port。TDD 目前只寫「Server logs 印 warning」不夠。 -
D→Arch-03 [🟡] Single-instance 第二次雙擊的 UX 未定義。
tray-and-lifecycle.md §2.3說收到/ipc/raise會WindowShow(ctx)浮到前面。Design 需要確認:- 第二個程序啟動是完全靜默(只 raise,沒有任何提示)還是顯示 toast(「已有另一個 visionA-local 在執行中」)?
- macOS 從 Dock click 的行為由 Cocoa 處理,但 Linux AppImage 每次都是新程序,體驗不一致——Design 建議三平台統一走「靜默 raise + 可選 toast」。
- 如果
raiseExistingInstance()失敗(例如 IPC port 讀不到),目前邏輯是覆寫 lock、視為新程序——這會造成使用者看到「兩個視窗」,非常糟糕。建議改為「失敗即顯示錯誤 modal + 退出」。
-
D→Arch-04 [🟡] Python sidecar crash 的 UI 呈現缺失。
tray-and-lifecycle.md §4.3寫「Python sidecar 空閒 N 分鐘自動 kill、崩潰時 Go server 自動重啟最多 3 次」。Design 需要知道:- 重啟那 1-2 秒使用者會看到什麼?目前的推論畫面會卡住/白屏?
- 3 次失敗後呈現的錯誤頁需要內容(Design
08-states.md只有通用 Critical error template,沒有 sidecar-specific)。 - 自動 kill(閒置省記憶體)後下一次使用者點推論,Design 需要顯示「正在重新啟動推論引擎...」spinner,否則 Start 按鈕按下後會有 2-3 秒無回應。
建議 Architect 新增事件
POST /ws/server-logs類型sidecar.state讓前端訂閱,Design 才能做對應 UI。
-
D→Arch-05 [🟡] Python 雙策略(A 內嵌 / B 系統)切換沒有 UI 入口。
dependency-bundling.md §1.5寫可透過--python-mode=bundled|systemCLI flag 切換,但使用者不會跑 CLI。Design 規格 Settings > 進階 應該有「Python 執行模式:內嵌(目前)/ 系統/ 自動」的唯讀顯示 + 重設按鈕。Design 這邊會補 wireframe,但需要 Architect 確認前端能讀.installedmeta 的 API(目前/api/system/deps是否涵蓋?)。 -
D→Arch-06 [🟡] 資料目錄遷移/升級情境未處理。 Architect 第三輪把 macOS 資料目錄從
~/.visiona-local/改到~/Library/Application Support/visiona-local/(Q-E1),但edge-ai-platform舊使用者可能已有~/.visiona-local/的資料。雖然 visionA-local 是新專案沒有「升級」概念,但如果使用者曾經裝過 edge-ai-platform 的 local 模式(有些人可能有),啟動時要不要偵測舊路徑、詢問是否遷移?Design 建議:M1 範圍內不處理,但 First-Run 增加一段說明「若你之前用過舊版 visionA,請手動搬移~/.visiona-local/到新路徑」。Architect 是否同意不自動遷移? -
D→Arch-07 [🟢]
watchServer()健康檢查頻率 10 秒對 UX 太慢。tray-and-lifecycle.md §4.2寫每 10 秒 healthcheck、失敗 3 次才判定掛掉,代表使用者最糟要等 30 秒才看到錯誤。建議縮短為「每 3 秒、失敗 2 次」= 6 秒內可感知。 -
D→Arch-08 [🟢] macOS 第二個程序的
⌘N「新增視窗」語意未定義。 砍掉 tray 後,feature-inventory.md §4.5提到 menu bar 有「File → New Device」。但 macOS 慣例 File menu 常有「New Window (⌘N)」——我們是單例 app,這個快捷鍵要完全拿掉還是改成「新增裝置」?Design 建議改成「New Device (⌘N)」避免衝突。
📋 R9 Plan B 的 First-Run 下載流程草案
若 Kneron 不允許 re-distribution,預置 .nef 無法內嵌,首次啟動必須線上下載 ~73MB 模型。Design 設計以下 fallback UX:
流程修改: 在現有 First-Run Step 2(模式選擇)與 Step 3(硬體偵測)之間插入一個新步驟 2.5「下載預置模型」。
Step 1 歡迎 → Step 2 模式選擇 → [NEW] Step 2.5 下載模型 → Step 3 硬體偵測 → Dashboard
Step 2.5 Wireframe:
┌─────────────────────────────────────────────────────┐
│ [略過 →] │
│ │
│ 下載預置 AI 模型 │
│ 首次使用需要下載約 73 MB 的範例模型 │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 📦 fd_mask.nef 14 MB ✓ │ │
│ │ 📦 yolov5s.nef 18 MB ⟳ │ │
│ │ 📦 resnet50.nef 22 MB … │ │
│ │ 📦 mobilenet.nef 8 MB … │ │
│ │ 📦 tiny_yolo.nef 11 MB … │ │
│ └──────────────────────────────────────┘ │
│ │
│ 整體進度:[■■■■□□□□□□] 40% (29 MB / 73 MB) │
│ 預估剩餘:45 秒 │
│ │
│ 來源:Innovedus 內部 CDN │
│ │
│ ⓘ 若要完全離線使用,請聯絡 IT 取得完整安裝包 │
│ │
│ [取消下載] [暫停] │
│ │
│ 2.5 / 3 │
└─────────────────────────────────────────────────────┘
互動規則:
- 離線偵測:Wails app 啟動時先 ping Innovedus 內部 CDN(HEAD 請求,5 秒 timeout)。無法連線 → 顯示「離線提示卡」:「目前無法連線到模型伺服器。你可以 (A) 稍後重試 (B) 改用 Mock 模式 (C) 手動放置 .nef 到
<APPDATA>/data/nef/」。 - 斷線續傳:每個模型用獨立 HTTP request,失敗可單獨重試,不重新下載已完成的。
- 跳過:「略過」→ 直接進 Step 3,但 Models 頁會顯示空狀態「還沒有預置模型,請到 Settings > 進階 下載」。
- 完成條件:至少 1 個模型下載成功即可繼續;0 個則強制退回 Step 2 選 Mock。
- Settings 入口:Settings > 進階 新增「重新下載預置模型」按鈕,使用者可隨時補。
連帶影響(給 PM): PRD §6.4「離線可用」承諾必須加註解:「例外:若 R9 Plan B 觸發,首次啟動需一次性下載 ~73 MB 預置模型。後續使用仍完全離線。」
Design 估計:Plan B 的 First-Run UI 工作量約 0.5 人週(只新增 1 個 step + 1 個 Settings 按鈕 + 文案)。
❓ 需要使用者或三方討論的問題
- D→PM-01 的 AC 拆分:使用者想要「15 秒」適用於所有情境,還是接受「首次 30 秒 / 回訪 15 秒」?
- D→Arch-02 的實際 port 顯示位置:Settings > 進階?還是 Dashboard Server 狀態卡?
- D→Arch-06 舊專案資料目錄遷移:要不要自動偵測
~/.visiona-local/並提示使用者? - R9 Plan B 觸發時,內部 CDN 是否可用?PM 需要與 Innovedus IT 先確認,避免 Plan B 時再花時間找 host。
- macOS
⌘N快捷鍵(D→Arch-08):要綁什麼動作?
結論
整體結論:三方文件一致性高,砍 tray、Workspace 升一級、Settings 4 分頁、macOS 資料路徑這幾個第三輪決策都有落實到各自的文件裡。
主要風險在於三層程序的啟動時間沒有被端到端量化(D→Arch-01),這會直接影響到 First-Run 與 NFR §6.1 的 AC 能不能達成,建議 Architect 在 M1 結束時就實測並回填。
次要問題是一些邊界情境的 UX 未被 Architect 顯式處理:port picking 的 UI 呈現、second-instance 的提示、sidecar crash/auto-kill 的 loading 狀態、Python 雙策略的切換入口。這些不是 blocker 但會影響「順手、穩定」的使用體驗,建議 Architect 在 M3 前補齊 API 事件(sidecar.state、實際 port 查詢)讓 Design 能接著做 UI。
R9 Plan B 的 First-Run 下載流程已草擬,Design 工作量可控(~0.5 人週),但內部 CDN 可用性需要 PM 先確認,避免真的觸發 Plan B 時措手不及。
Design Agent 對 PRD 與 TDD 第三輪版的整體結論:原則上可進入實作階段,但上述 🔴 問題 2 條(D→Arch-01、D→Arch-02)建議在 M1 開始前先補,避免後續返工。其餘 🟡 🟢 可在 M2-M3 迭代解決。