visionA/local-tool/.autoflow/06-testing/m9-5-validation-plan.md
jim800121chen 8c27da7cca test(local-tool): M9-5 — three-platform validation plan + e2e scripts + MJ3 fix
A 階段最後 milestone、出測試計畫 + 自動化腳本 + 三平台人工 checklist、使用者下週手動跑實機驗證。

Testing artifacts (8 檔、2630 行):
- .autoflow/06-testing/m9-5-validation-plan.md: 656 行(4 情境 × 3 平台 × 2 chip = 24 combo)
- 4 e2e specs (vitest + RTL + mock WS / mock fetch):
  - firmware-upgrade-happy-path.spec.ts (357 / 4 cases)
  - firmware-upgrade-error-recovery.spec.ts (356 / 4 cases + 8 reason it.each)
  - firmware-r-fw-11-modal-not-closable.spec.ts (303 / 6 cases)
  - wails-onbeforeclose-firmware-active.spec.ts (217 / 9 cases、含 5 todo 占位 M9-12)
- 3 manual checklists: macOS 264 / Windows 234 / Linux 243 行

設計取捨:
- 不引入 Playwright/Cypress (visionA-local frontend 沒裝、屬 architect 決策)、走 vitest + mock
- E2E 腳本放 06-testing/scripts/ 作 spec doc + 可選實作參考
- 實機驗證走人工 checklist (dongle 插拔 / kill process / SIGTERM 等需要實體互動)

MJ3 修復 (M9-4 reviewer round 1 留的 follow-up):
- server/internal/api/ws/firmware_ws_test.go: +16/-8
- "type": "firmware:progress" → "firmware_progress" (對齊 firmwareProgressMessage.Type)
- "phase" → "stage" (對齊 TDD §4.2 + FirmwareProgress.Stage)
- 不動 production code、只 test schema 對齊

執行建議 (給你下週):
- Day 1 P0: macOS+Win+Linux × KL520+KL720 happy path (~3h)
- Day 2 P1: R-FW-11 + disconnect_during_op + upgrade_mid_failed + 失敗注入 (4h)
- Day 3 P2: SIGTERM 延遲關閉 + Wails OnBeforeClose force-quit modal (2-3h)

測試:
- go test ./... -race 全綠 (server / wails / frontend 60 tests)
- MJ3 修復不破壞既有測試

A 階段開發 6/7 完成 (M9 文件 + M9-1 ~ M9-4.5)、剩 M9-5 實機驗證 (你下週跑)、跑完依結果決定 A 階段交付或派 sub-agent 修。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:34:17 +08:00

29 KiB
Raw Blame History

M9-5 三平台實機驗證計畫 — Kneron Dongle FW 升降版

對應 PRD.autoflow/02-prd/features/feature-firmware-management.mdAC-FW-1.1 ~ AC-FW-1.9 對應 TDD.autoflow/04-architecture/v2/firmware-management.md §11測試策略 對應 Design.autoflow/03-design/v2/firmware-management.md §7失敗復原 UX 8 種) 階段:A 階段最後 milestoneM9-5、1 人天、Testing 出 plan + 自動化腳本、使用者下週實機驗證) 版本v1.02026-05-25 作者Testing Agent


0. 文件結構導覽

章節 主題
§1 範圍與驗證目標
§2 測試環境前置(硬體 + 軟體)
§3 三平台 × 兩 chip × 四情境 × 一致驗證表24 combo
§4 功能性驗證Functional — happy path、4 情境
§5 可靠性驗證Reliability — 失敗注入 8 種 reason
§6 效能驗證Performance — 升級時長護欄
§7 UX 驗證 — badge / modal / 復原 UI / R-FW-11 modal 不可關
§8 整合驗證 — SIGTERM / Wails OnBeforeClose / force-quit modal
§9 自動化腳本對照表E2E unit-style + 手動 checklist
§10 通過 / 失敗判定規則
§11 Bug 回報格式
§12 下週執行建議順序(哪平台先 / 哪情境先)
§13 Pass → next-step / Fail → 派工建議

1. 範圍與驗證目標

1.1 範圍邊界

在範圍M9-5 必驗):

  • KL520 + KL720 兩 chip 的 FW 升級流程A 階段、KDP1 → KDP2 + KDP2 → KDP2 short-circuit
  • macOS / Windows / Linux 三平台
  • 4 個升級情境§4.1
  • 8 種失敗注入路徑§5.2
  • AC-FW-1.1 ~ AC-FW-1.9 全部 acceptance criteria
  • §8.6 graceful shutdown + Wails OnBeforeClose force-quit modal

不在範圍B 階段或 post-launch

  • KL630 / KL730 升降版B 階段 M9-10 才開、AC-FW-3.5
  • 手動降版B 階段 M9-11/12
  • 多版本目錄結構B 階段 M9-9
  • KneronPLUS wheel 升 3.1.2 跨主版本回歸B 階段 M9-13
  • Beta usability testUR-1~3、post-launch

1.2 驗證目標pass criteria

類別 目標
Functional 4 情境 × 6 combo3 平台 × 2 chip= 24 個升級實驗、success rate ≥ 95%
Reliability 8 種 reason 注入測試、UI friendly message 正確顯示、no server crash
Performance KL520 ≤ 60s 上界、KL720 ≤ 200s 上界AC-FW-1.7 + TDD §7.2 護欄)
UX Badge 4 色顯示正確、modal 不可關R-FW-11、復原 UI 對應 8 種 reason
Integration SIGTERM 延遲關閉、Wails OnBeforeClose force-quit modal 阻擋成功

2. 測試環境前置

2.1 硬體(使用者已備齊)

項目 說明
KL520 dongle USB Boot 版KDP1 legacy+ KDP2 standard 版各 1 根;若只有 KDP2 dongle、可從 KDP2 跑 short-circuit 路徑
KL720 dongle 至少 1 根(已預燒 KDP2、會走 short-circuit
macOS 機器 Apple Silicon 或 Intel x86_64兩者皆可
Windows 機器 Windows 10/11、x86_64、有 admin 權限KneronPLUS WinUSB driver
Linux 機器 Ubuntu 20.04+ 或同等 distro、udev rules 已綁定
USB hub 推薦(拔插測試方便、不必碰主機 port

2.2 軟體

每平台需要:

  • visionA-local 最新 A 階段 build含 M9-1 ~ M9-4 commits
  • Chrome / Edge / Firefox 任一(測 UI、瀏覽器 tab
  • Terminal / Console看 server log、跑 git log 等)

2.3 測試資料

  • 純淨環境:每平台跑前刪 ~/Library/Application Support/visiona-local/ 或同等位置、確保沒有 leftover state
  • KL520 KDP1 dongle 是必要的(最重要的 happy path若沒有、降級為「KDP2 short-circuit only」+ §11 bug-report 指出此 gap

3. 三平台 × 兩 chip × 四情境驗證表

每個 cell = 1 個驗證實驗。理想全部 ,部分 ⚠ partial 可接受、 阻擋發布。

# 平台 Chip 情境 預期 stage 序列 timeout 上界 驗證標準
1 macOS KL520 KDP1 → KDP2 完整升級4 stage preparing → loading → flashing → verifying → done 60s §4.1 情境 A
2 macOS KL520 KDP2 → KDP2 short-circuit3 stage preparing → flashing → verifying → done 60s §4.1 情境 B
3 macOS KL720 KDP2 升級 / load_firmware_from_file preparing → flashing → verifying → done 200s §4.1 情境 C
4 Windows KL520 KDP1 → KDP2 完整升級 同 1 60s §4.1 情境 A
5 Windows KL520 KDP2 short-circuit 同 2 60s §4.1 情境 B
6 Windows KL720 KDP2 升級 同 3 200s §4.1 情境 C
7 Linux KL520 KDP1 → KDP2 完整升級 同 1 60s §4.1 情境 A
8 Linux KL520 KDP2 short-circuit 同 2 60s §4.1 情境 B
9 Linux KL720 KDP2 升級 同 3 200s §4.1 情境 C
10 macOS KL520 來回升級(情境 A 完成後再跑 A 兩次 1 stage 序列 各 60s §4.1 情境 D
11 Windows KL520 來回升級 同 10 各 60s §4.1 情境 D
12 Linux KL520 來回升級 同 10 各 60s §4.1 情境 D

Functional combo = 123 平台 × 2 chip × 2 主情境 = 12情境 D 是延伸驗證、加 3 combo = 15、但 reliability + UX + integration 各加部分 combo、合計約 24 個實驗)。

Reliability 額外實驗

  • 13-20每平台跑「拔 USB 中斷」「kill bridge.py」「kill server」「modal R-FW-11 不可關」4 種注入,至少 macOS + Windows 各 4 = 8 comboLinux 補上 = 12

Integration 額外實驗

  • 21-24每平台跑「升級期間關 Wails 視窗→force-quit modal」「升級期間 SIGTERM→延遲關閉」2 種、合計 6 combo

合計 ~24 個 combo使用者可依時間裁切§12 給優先順序)。


4. 功能性驗證Functional

4.1 4 個升級情境(每平台 × 每 chip 都跑)

情境 AKDP1 → KDP2 完整升級4 stage、AC-FW-1.2

前置條件:插一根 KL520 KDP1 legacy donglefirmware 字串 KDP Comp/U 或類似)。

測試步驟

  1. 確認 visionA-local 已啟動、瀏覽器開 Devices 頁
  2. 確認偵測到 dongle、卡片右上角 FW badge 紅色 + 文字「KDP1 (legacy)」+ tooltip「此韌體為舊版 KDP1...」
  3. 點卡片內「升級到最新」按鈕labels升級到 v2.2.0
  4. 確認 confirm modal 顯示:
    • 標題「升級韌體」
    • from/tofrom = KDP1、to = v2.2.0
    • 警告:「升級過程約需 30 秒、期間切勿拔除裝置或關閉應用程式」
    • 「開始升級」按鈕primary、不是 destructive
  5. 點「開始升級」、modal 切到 upgrading phase
  6. 確認 progress modal
    • 不顯示 ✕ / 取消按鈕R-FW-11 緩解)
    • progress bar 從 0% 開始
    • 階段文字依序變化:「階段 1 / 4準備偵測 + 連接裝置)」→「階段 2 / 4載入引導程式」→「階段 3 / 4寫入韌體」→「階段 4 / 4驗證完成」
    • 紅色 banner「請勿拔除裝置」全程顯示
    • 「已耗時」秒數遞增、「預估剩餘」秒數遞減(依 etaMs 計算)
    • ESC / 點外部不關 modal捕獲、抖動或無反應
  7. 升級成功30 秒內、modal 短暫顯示綠勾 ✓ 「完成」+ afterVersion v2.2.0
  8. 約 1.5 秒後 modal 自動關閉
  9. 右上角 toast 出現「KL520 #1 升級成功 — 從 KDP1 升級到 v2.2.0(耗時 X 秒)」、停留 6 秒
  10. Devices 卡片 FW badge 變綠、firmware version v2.2.0

Pass 條件

  • 全部步驟完成、所有 UI 元素如預期
  • 升級在 60s 內完成KL520 timeout 上界)
  • 4 stage 全部出現、順序正確
  • Server log 沒有 panic、error

情境 BKDP2 → KDP2 short-circuit3 stage

前置條件KL520 dongle 已是 KDP2、firmware 字串為 v2.1.0v2.2.x 但比 bundled current 舊(觸發 yellow badge。或情境 A 跑完後重新跑情境 B。

測試步驟

  1. Devices 頁卡片 FW badge 黃色older
  2. 點升級按鈕、confirm modal
  3. 點「開始升級」、modal 切 upgrading
  4. 確認 progress stage 序列:3 stage(不是 4「階段 1 / 3準備」→「階段 2 / 3寫入韌體」→「階段 3 / 3驗證完成」沒有 loading 階段)
  5. 升級成功、badge 變綠

Pass 條件

  • 3 stage 而不是 4 stage核心差異、stageOrdinal helper 邏輯驗證)
  • 升級在 60s 內完成

情境 CKL720 升級

前置條件KL720 donglefirmware 為 KDP2可能與 bundled current 一樣或舊)。

測試步驟

  1. Devices 頁卡片 badge綠 (若 already current) 或黃 (older 可升)
  2. 若是黃色,點升級
  3. 同情境 A/B但 estimated duration 標 3 分鐘180 秒)
  4. progress modal stage 序列同 KDP2 short-circuit

Pass 條件

  • 升級在 200s 內完成KL720 timeout 上界)
  • progress 跑滿且沒有卡死

情境 D來回升級regression

前置條件:情境 A 已跑完、再跑一次完整 KDP1 → KDP2 升級流程(如果有第二根 KL520 KDP1 legacy dongle建議用第二根否則只能跑一次

測試步驟

  1. 重新跑情境 A
  2. 確認第二次升級不會:
    • 被「Error 15 SEND_DATA_TOO_LARGE」打斷既有 KL520 reset bug fix 應該已處理 needsReset=true
    • bridge.py 帶舊 firmware state 連線
  3. 第二次升級流程跟第一次完全一樣

Pass 條件

  • 沒有 Error 15
  • 連續兩次升級都成功

4.2 多裝置同時升級per-device 隔離、firmware-store activeDeviceId 機制)

前置條件:兩根 dongle 同時連接(建議 1× KL520 + 1× KL720

測試步驟

  1. Devices 頁顯示兩張卡片
  2. 點 KL520 卡片的升級按鈕modal 開)
  3. 升級進行中、切回 Devices 頁 看另一張 KL720 卡片狀態
  4. 點 KL720 卡片的升級按鈕 — 預期:會被擋住(因為 firmware-store 一次只允許一個 activeDeviceId、其他 device 的事件被忽略)
    • 或者 modal 開但顯示「裝置正在進行其他作業」409 FW_DEVICE_BUSY
  5. 等 KL520 完成
  6. 點 KL720 升級、流程正常

Pass 條件

  • 第一個升級進行中、不會被第二個 modal 蓋掉
  • Frontend store 不出現「兩個 progress event 互相覆蓋」

5. 可靠性驗證Reliability、失敗注入

5.1 對應 Design §7.1 的 8 種失敗類型

# 失敗類型 注入方法 預期 reason 預期 UI
1 scan_not_found 升級前拔 USB → 立刻點升級 scan_not_found error modal「找不到裝置」+「重新插拔後重試」按鈕
2 connect_failed 多開 visionA-local兩 instance 搶 device→ 點升級 connect_failed 「無法連接裝置」+「重試」按鈕
3 loader_write_failed 升級到 loading stage 時 pkill -9 python loader_write_failed 「引導程式載入失敗」+「拔插後重試」
4 upgrade_mid_failed 升級到 flashing stage 時 pkill -9 python upgrade_mid_failed 「韌體寫入失敗、聯絡技術支援」+「複製錯誤訊息」+「取得協助」mailto:
5 disconnect_during_op 升級到 flashing stage 時拔 USB disconnect_during_op brick warning banner + 「Contact Support」不顯示 retry 按鈕
6 timeout 修改 bridge.py 加 time.sleep(70) 模擬 KL520 ≥ 60s或 KL720 ≥ 200s timeout 「操作超時」+「拔插後重新掃描」
7 verify_mismatch 升級成功但 backend 偽造 firmware 字串不對(需 mock 或實機難以重現) verify_mismatch brick warning + ContactSupport
8 verify_not_found 升級成功但 rescan 找不到 device verify_not_found brick warning + ContactSupport

實機限制#7 verify_mismatch / #8 verify_not_found 在實機很難穩定重現、建議用 E2E 自動化mock backend覆蓋。

5.2 注入測試步驟模板

對每個失敗類型:

  1. 啟動 visionA-local
  2. 跑情境 A 或 B 升級流程到 confirm modal
  3. 點「開始升級」、進入 upgrading phase
  4. 等到指定 stage、執行注入動作拔 USB / kill process / etc.
  5. 觀察 UI 變化
  6. 截圖 + 紀錄 timestamp

5.3 重點驗證項

對每個失敗:

  • error modal 顯示對應 friendly message中文 / 英文視 i18n 設定)
  • 顯示 errorCodeFW_E102
  • 技術資訊區可展開、包含 stage / reason / deviceId / rawError
  • 「複製錯誤訊息」按鈕可點、複製成功變「已複製 ✓」
  • 若是 destructive reasondisconnect/verify_mismatch/verify_not_found
    • 顯示 brick warning role=note
    • 不顯示 Retry 按鈕
    • 顯示「Contact Support」destructive 按鈕enabled、點擊開 mailto:
  • 若是 recoverable reason其他
    • 顯示 Retry / ReplugRetry / Rescan 按鈕
    • 點 Retry 後流程重啟store 回 confirming phase + 重新打 API
  • Server log 無 panic、無 crash
  • Devices 頁卡片狀態不會卡住、re-plug 後可繼續用

6. 效能驗證Performance

6.1 升級時長護欄AC-FW-1.7、TDD §7.2

Chip 預估 護欄上界 護欄超過行為
KL520 ~30swarrenchen 實測) 60s timeout、UI 顯示 Reason="timeout"
KL720 ~180swarrenchen 實測) 200s timeout、UI 顯示 Reason="timeout" + FW_UPGRADE_BRICK_RISK

6.2 量測方法

對每個 functional 升級實驗§3 表格 1-12

  1. 開瀏覽器 DevTools Network tab、觀察 WS 「firmware_progress」event 時序
  2. 紀錄:
    • stage=preparing event 第一次出現的 timestamp
    • stage=done event 出現的 timestamp
    • 差距 = 升級實測時長
  3. 對照表格:
Combo 預期時長 實測時長 Pass / Fail
macOS × KL520 × KDP1→KDP2 < 60s
macOS × KL520 × short-circuit < 60s
macOS × KL720 < 200s
Windows × KL520 × KDP1→KDP2 < 60s
...

Pass 條件:所有 combo 升級時長 ≤ 護欄上界。 Warn 條件:時長 > 預估但 < 護欄、log 為 P3 改善項。 Fail 條件:時長 ≥ 護欄、阻擋發布、回 Backend 派工調 timeout / 修流程。

6.3 progress event 推送頻率

  • 預期:每 stage 切換時推 1 個 event、每秒至少 1 個 event含 ETA 更新)
  • 若 stage 間 > 10s 沒有 eventUI ETA 失準、log 為 Backend P2 改善項

7. UX 驗證

7.1 Badge 4 色狀態AC-FW-1.1

State 條件 顏色 文字
current firmwareVersion = bundled current 版本字串(如 v2.2.0
older firmwareVersion 比 current 舊(同 KDP2 系列) 版本字串
legacy firmwareIsLegacy = trueKDP1 KDP1
unknown firmwareVersion 或 bundled 為空 / unknown UnknownLoading...

測試步驟

  1. 在三平台分別跑:插一根 KDP1 legacy dongle、確認紅 badge
  2. 升級到 v2.2.0 後、確認綠 badge
  3. 修改 bundle CURRENT_VERSION如果 A 階段沒實作則此步驟跳過、由 B 階段 M9-9 驗)→ 確認黃 badge
  4. 拔 USB → 卡片消失(不該顯示灰 badge、直接 device 不在清單)
  5. 連線中 bridge.py 沒回 firmware 字串 → 顯示灰 badge過渡狀態

7.2 升級 modal R-FW-11「不可關」驗證AC-FW-1.9

升級 upgrading phase 期間驗證:

  • ✕ 按鈕不存在DialogContent showCloseButton={false}
  • ESC 不關閉 modal
  • 點 modal 外部(黑色 overlay不關閉
  • 「取消」按鈕不存在
  • 即使刷新瀏覽器頁面後再回來、升級期間仍在進行progress modal 由 store 重新 hydrate

7.3 失敗 modal 復原 UIDesign §7.2

Reason 主要按鈕 次要按鈕
scan_not_found 「重新插拔後重試」 關閉
connect_failed 「重試」 關閉
loader_write_failed 「拔插後重試」 關閉
upgrade_mid_failed 「重試」 關閉
timeout 「拔插後重新掃描」 關閉
disconnect_during_op 「Contact Support」destructive、mailto: 關閉、無 retry
verify_mismatch 「Contact Support」 關閉、無 retry
verify_not_found 「Contact Support」 關閉、無 retry

每種失敗都驗:

  • 主要按鈕文案正確
  • destructive reason 不顯示 Retry
  • Contact Support 點擊開 mailto: handlersubject + body 帶 errorCode + 技術資訊)
  • 「複製錯誤訊息」可複製、變「已複製 ✓」2 秒後復原
  • errorCode 以 mono 字型顯示

7.4 Success toast 行為

  • toast 顯示「{deviceName} 升級成功 — 從 X 升級到 Y耗時 N 秒)」
  • toast 停留 6 秒(不是預設 4 秒)
  • toast 自動消失、不需手動關
  • 升級成功後 Devices 頁自動 refresh、badge 變綠

8. 整合驗證Integration

8.1 升級期間 SIGTERM 延遲關閉TDD §8.6.1

測試步驟

  1. macOS / Linux找出 server PIDps aux | grep visiona-local-server 或 visionA-local 控制台顯示)
  2. 啟動升級流程(情境 A 或 C、長一點的
  3. 升級到 flashing stage 時、執行 kill -TERM <PID>
  4. 預期:
    • server 不立即退出
    • 透過 WS 廣播 server:shutdown-pending event 到 "system" room
    • shutdown 延遲到 firmware task 完成(最多 firmware.MaxShutdownWait = 220s
    • firmware task 跑完才走原本 graceful shutdown 流程
  5. 觀察 server log、應有
    • firmware: N active firmware task(s) detected, delaying shutdown up to ...
    • firmware task 完成後、firmware: all firmware tasks completed, proceeding to shutdown
  6. 升級結束後、server 才真正退出
  7. Frontend modal 在 server 退出前該完成正常的 upgrade success toast 流程

Pass 條件

  • server 不在升級進行中退出(不 brick
  • SIGTERM event log 有 delaying shutdown 紀錄
  • 升級成功完成、device 升級後狀態正常

8.2 Wails OnBeforeClose force-quit modalTDD §8.6.2 + visiona-local/firmware_close_guard.go

測試步驟

  1. 任一平台 + 任一 chip
  2. 啟動升級流程(情境 A 或 C
  3. 升級到 flashing stage 時、點 Wails 視窗的 ✕ 關閉按鈕macOS紅色關閉、Windows右上 ✕、Linuxwindow manager close
  4. 預期:
    • Wails 視窗 不關閉
    • Wails 收到 OnBeforeClose 後查 /api/firmware/active-taskshasActive: true
    • emit Wails event app:firmware-in-progress 帶 task payload
    • Frontend modal 攔截、顯示「韌體切換進行中、為避免裝置損毀、無法關閉應用程式」
    • modal 顯示 task infodevice name / chip / direction / stage / elapsedMs / etaSeconds
    • modal 顯示「繼續等待」primary、回到原本升級流程+ 「強制關閉」destructive按鈕
  5. 點「強制關閉」、預期第二層 FORCE 確認 modal要使用者輸入「FORCE」字串
  6. 不輸入 / 取消 → 升級繼續、modal 關閉、Wails 視窗回到正常
  7. 輸入「FORCE」+ 確認 → ConfirmForceClose binding 被叫、Wails 走 graceful shutdown會 brick 裝置、風險已接受、Design §6a
  8. 升級正常結束(不點強制關閉的情境)後、再點 ✕ → Wails 正常關閉

Pass 條件

  • 升級進行中視窗無法關
  • force-quit modal 顯示 + payload 正確
  • 第二層 FORCE 確認可運作
  • 升級完成後視窗正常可關

8.3 升級期間 server crash 容忍

測試步驟

  1. 升級進行中、kill -9 <server-PID>(強制殺、不走 graceful shutdown
  2. Frontend WS 應於 3 秒內偵測到斷線、自動重連嘗試
  3. server 重啟後(手動 / Wails 自動、Frontend bootId 機制應觸發 reload
  4. Devices 頁應重新 scan、卡片回到「device 連線中」或「沒有 device」狀態
  5. 觀察 dongle 實體狀態 — 可能 brick取決於升級 stage、屬接受風險、TDD §8.6.1 hard timeout 後也走 shutdown

Pass 條件

  • Frontend 不卡死、UI 可繼續操作
  • Server 重啟後狀態正常
  • ⚠ Dongle 可能 brick屬接受風險、需給技術支援 SOP 救磚)

9. 自動化腳本對照表

測試類型 涵蓋方式 對應檔
Backend smoke schema 對齊MJ3 已修、go test 全綠 server/internal/api/ws/firmware_ws_test.go
Frontend store 邏輯 已有 vitest 60 tests 全綠 frontend/src/tests/stores/firmware-store.test.ts
Frontend componentbadge / error view 已有 vitest 全綠 frontend/src/tests/components/firmware-*.test.tsx
E2E happy pathmock WS + UI M9-5 新增 vitest 風格 .autoflow/06-testing/scripts/firmware-upgrade-happy-path.spec.ts
E2E 失敗注入8 reason × UI M9-5 新增 vitest 風格 .autoflow/06-testing/scripts/firmware-upgrade-error-recovery.spec.ts
E2E R-FW-11 modal 不可關 M9-5 新增 vitest 風格 .autoflow/06-testing/scripts/firmware-r-fw-11-modal-not-closable.spec.ts
E2E Wails OnBeforeClose 攔截邏輯 M9-5 新增unit-style on Go .autoflow/06-testing/scripts/wails-onbeforeclose-firmware-active.spec.ts
三平台實機驗證 人工 checklist .autoflow/06-testing/scripts/manual-checklist-{macos,windows,linux}.md

注意:因為 visionA-local 沒有 Playwright / Cypress、實機驗證需要實體 dongle、E2E 腳本走 vitest + RTL + mock WS / mock fetch 路線,模擬 backend 整條 stage 流轉、frontend 跑真實 component build。實機驗證走人工 checklist§12


10. 通過 / 失敗判定規則

10.1 P0阻擋發布

任一發生 → A 階段不可進入發布流程:

  • Functional 升級成功率 < 90%24 combo 中 ≥ 3 個失敗)
  • 升級期間 server crash / panic
  • 升級期間 dongle 100% brick無法復原
  • §8.1 SIGTERM 期間 server 不延遲關閉(直接中斷 firmware task
  • §8.2 Wails 視窗在升級進行中可直接關閉OnBeforeClose 沒生效)

10.2 P1嚴重但可繞過

任一發生 → 開 P1 bug ticket、視 release window 決定是否阻擋:

  • 升級時長 > 護欄但 < 護欄 × 1.5KL520 60-90s / KL720 200-300s
  • Frontend store 多裝置隔離失效(兩個 progress modal 互相覆蓋)
  • destructive reason 仍顯示 retry 按鈕
  • force-quit modal 第二層 FORCE 確認字串可繞過

10.3 P2一般問題

  • Badge 顏色顯示錯誤(如 older 顯示成 current
  • toast 持續時間錯誤
  • i18n key 漏譯 / 文案錯誤

10.4 P3改善建議

  • progress event 推送頻率太低(卡頓 > 5s
  • error modal 「技術資訊」展開後排版錯亂

11. Bug 回報格式

對每個發現的問題,使用以下格式回報到 .autoflow/06-testing/bugs/M9-5-BUG-{NN}.md

# M9-5-BUG-NN: [標題]

## 嚴重程度P0 / P1 / P2 / P3
## 發現方式Functional / Reliability / Performance / UX / Integration
## 環境macOS 14.3 / Windows 11 / Ubuntu 22.04
## 對應驗證§4.1 情境 A / §5.1 #3 loader_write_failed / etc.
## 對應 ACAC-FW-1.X / R-FW-11 / R-FW-13

## 重現步驟
1. ...
2. ...

## 預期行為
(依 PRD / TDD / Design Spec、引用具體章節

## 實際行為
(觀察到的差異)

## 截圖
(路徑:.autoflow/06-testing/screenshots/M9-5-bug-NN-{step}.png

## Server log 片段

(從 ~/Library/Application Support/visiona-local/wails.log 或對應位置)


## Frontend WS event log

(從 browser DevTools Network → WS frames


## 建議修復方向(如有)
(不一定要、但 testing 觀察過程的線索)

12. 下週執行建議順序(給使用者)

12.1 第 1 天smoke + happy path必驗、~3 小時)

優先順序:

  1. macOS × KL520 × KDP2 short-circuit(最快、不需 KDP1 dongle、5 分鐘)
  2. macOS × KL520 × KDP1 → KDP2 完整升級happy path 核心、10 分鐘)
  3. macOS × KL720 × 升級(單一 chip 驗證、5 分鐘 + 3 分鐘升級 = 10 分鐘)
  4. 重複 1-3 在 Windows
  5. 重複 1-3 在 Linux

→ 若 macOS 1-3 全綠、且 Windows / Linux 至少 1 個 combo 綠、可進入第 2 天。 → 若 macOS 任一失敗:停下、回報 bug、不繼續其他平台。

12.2 第 2 天reliability + UX4 小時)

對 macOS或第 1 天最穩的平台)跑:

  1. R-FW-11 modal 不可關5 分鐘)
  2. Badge 4 色顯示10 分鐘)
  3. 失敗注入 #1 scan_not_found5 分鐘)
  4. 失敗注入 #3 loader_write_failed10 分鐘)
  5. 失敗注入 #4 upgrade_mid_failed10 分鐘)
  6. 失敗注入 #5 disconnect_during_op10 分鐘)
  7. 失敗注入 #6 timeout10 分鐘)
  8. UX checklisttoast / 復原 UI / mailto: 開啟30 分鐘)

再對 Windows + Linux 跑 #5 disconnect_during_op + #4 upgrade_mid_failed兩個 brick risk 最高的)作為 sanity check。

12.3 第 3 天integration2-3 小時)

對任一最穩平台跑:

  1. §8.1 SIGTERM 延遲關閉macOS / Linux 推薦、Windows SIGTERM 不直觀)
  2. §8.2 Wails OnBeforeClose force-quit modal三平台都要驗

12.4 整體建議優先順序

P0 must-have必跑
  - §4.1 情境 A × 三平台(核心 happy path
  - §4.1 情境 B × 三平台short-circuit 驗證)
  - §8.2 Wails OnBeforeClose × 三平台(避免 brick

P1 should-have強烈建議
  - §4.1 情境 C × 三平台KL720 驗證)
  - §5.1 #5 disconnect_during_op × 三平台brick 風險最高)
  - §8.1 SIGTERM × macOS + Linux
  - §7.3 失敗 modal 復原 UI × 至少一個平台

P2 nice-to-have時間允許
  - §4.1 情境 D 來回升級 × 任一平台
  - §5.1 #1-4 + #6 其他失敗注入
  - §6 effective 時長量測

13. Pass → Next-step / Fail → 派工建議

13.1 Pass所有 P0 都綠 + P1 大部分綠)

→ A 階段可進入發布流程:

  1. 給 Orchestrator 「A 階段交付」訊號
  2. Orchestrator 啟動 Reviewer agent 對 M9-5 plan + scripts + manual checklist 做最終 review
  3. Reviewer 通過後、A 階段五人天宣告完成、可進入:
    • 法律合規確認Kneron firmware redistribution 授權、R-FW-5 / Q-FW-1
    • 發布 A 階段 visionA-local含 KL520/KL720 升級 only、KL630/KL730 延 B 階段)
    • 進入 B 階段 M9-6 強驗證 + M9-7 啟動

13.2 Fail任一 P0 失敗 / 多個 P1 失敗)

依失敗類型分流派工建議:

Fail 類型 派誰
§4.1 升級流程崩潰、stage 不正確 Backend修 firmware_handler / bridge.py / driver
§5 reason 對應錯誤、UI friendly message 沒顯示 Frontend修 firmware-store errorMessageKeyFor / firmware-error-view
§6 時長 ≥ 護欄 Backend調 bridge.py timeout 或優化流程)
§7.1 Badge 4 色錯誤 Frontend修 firmware-badge computeBadgeState
§7.2 R-FW-11 modal 可關 Frontend修 firmware-upgrade-dialog onOpenChange
§8.1 SIGTERM 不延遲 Backend修 firmware/shutdown.go + server/main.go signal handler
§8.2 Wails 視窗可關 Wails layer修 visiona-local/firmware_close_guard.go + frontend modal

回報給 Orchestrator 的 escalation 範本

[M9-5 驗證失敗]
- 失敗 combo[macOS × KL520 × KDP1→KDP2 / 情境 A]
- 失敗類型:[P0 升級流程崩潰]
- bug ticket.autoflow/06-testing/bugs/M9-5-BUG-NN.md
- 建議派工Backend修 bridge.py upgrade_mid 處理)
- A 階段交付狀態:阻擋

14. 附錄

14.1 重要 log 位置

平台 wails.log server.log
macOS ~/Library/Application Support/visiona-local/wails.log ~/Library/Application Support/visiona-local/server.log
Linux ~/.local/share/visiona-local/wails.log ~/.local/share/visiona-local/server.log
Windows %APPDATA%\visiona-local\wails.log %APPDATA%\visiona-local\server.log

14.2 重要 WS endpoint

  • ws://127.0.0.1:<port>/ws/devices/:id/firmware-progress — firmware progress room
  • broadcast type=firmware_progressstage=preparing|loading|flashing|verifying|done|error

14.3 重要 API endpoint

  • POST /api/devices/:id/firmware/upgrade — 觸發升級
  • GET /api/firmware/active-tasks — 查詢進行中 taskWails 用)

14.4 主要相依檔(給 bug 回報時引用)

角色
server/internal/firmware/service.go 升級 service goroutine
server/internal/firmware/shutdown.go SIGTERM graceful shutdown
server/internal/api/handlers/firmware_handler.go API + WS broadcast
server/scripts/kneron_bridge.py bridge.py upgrade handler
visiona-local/firmware_close_guard.go Wails OnBeforeClose
frontend/src/components/firmware/firmware-upgrade-dialog.tsx modal lifecycle
frontend/src/stores/firmware-store.ts phase / reason mapping

變更紀錄

日期 版本 變更 作者
2026-05-25 v1.0 初版 — M9-5 三平台實機驗證 plan + 自動化腳本對照表 + 人工 checklist 索引 + 下週執行建議順序 Testing Agent