visionA/local-tool/.autoflow/02-prd/features/feature-firmware-management.md
jim800121chen 46514d77d7 docs(local-tool): M9 — Kneron Dongle FW 偵測 + 升降版(A+B、翻案 R5-Q9)
L 級新功能、PRD/Design/TDD/ADR 三方協作 + 互審 + M9-6 SDK 雙驗證、總計 ~9000 行文件。

範圍:
- A 階段(MVP、5 人天):KL520 + KL720 自動升級 KDP1 → KDP2
- B 階段(10.5 人天):手動降版面向一般使用者 + KL630 / KL730 擴展
- 合計 15.5 人天、安裝包 +7MB(保守 bundle 策略)

關鍵決策:
- 翻案 R5-Q9(progress.md 第二輪使用者決策「韌體燒錄 flash → B 砍掉」)
- 跨平台用 KneronPLUS Python C API、不用 DFUT.exe
- 多版本目錄結構選 C metadata(firmware/<chip>/{version}/ + CURRENT_VERSION)
- Kneron firmware redistribution 授權與 R5-B4 預置模型同性質、發佈前評估

文件產出:
- PRD v2.2(PRD-v2.md 495 行 + features/feature-firmware-management.md 599 行)
- Design v2.2(firmware-management.md 948 行 + control-panel.md §6a graceful shutdown)
- TDD v2.2(v2/firmware-management.md 823 行 + ADR-001 218 行)
- 8 份 research(含 M9-6 弱驗證 + 強驗證、~3200 行)
- 3 份三方互審報告(PM/Design/Architect cross-review)

M9-6 強驗證重大發現(影響 B 階段):
- KL730 product_id 實際是 0x732(不是 0x0730)
- KL630/KL730 firmware 是 embedded Linux rootfs(不是 .bin、不同代設計)
- KneronPLUS Python 沒 update_kdp_firmware_from_files 公開 API、warrenchen 走 ctypes
- 不影響 A 階段、B 階段 M9-8 需 spike

下一步:派 backend M9-1 起跑(bridge.py handle_firmware_upgrade)

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

600 lines
46 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# feature: Kneron Dongle FW 偵測 + 升降版
> 對應 PRD[`PRD-v2.md`](../PRD-v2.md) v2.22026-05-24
> 作者PM Agent
> 任務等級L 級新功能(翻案 R5-Q9
> 範圍A 階段MVP+ B 階段(擴展),一次做完
> 預估工時A 5 人天 + B 10.5 人天 = **15.5 人天**
> 安裝包衝擊:+7MB保守 bundle 策略163MB → ~170MB
> 狀態:**v2.2.1 — 吸收三方互審 + M9-6 弱驗證結果裁決stage 命名採 Design / M9 工時拆法採 PM / AC-FW-3.5 延後 B 階段 M9-10**
---
## 0. 一句話摘要
讓使用者把插上的 Kneron Dongle 從「Error 15 完全不能用的舊 FW」一鍵升級到內建 KDP2 標準版本,並提供面向一般使用者的多版本切換 UI含降版全程離線可用、不需要 DFUT.exe 或外部工具。
---
## 1. 動機
### 1.1 真實痛點:拿到舊 dongle 完全不能用
2026-04-21 的 bug 紀錄progress.md §「2026-04-21 推論 bbox 標註不顯示 + KL520 Error 15」已具體記錄
- KL520 USB Boot dongle 若 session 間 firmware 殘留 `fw=KDP2 Comp/U`**直接 `load_model + inference` 100% 炸 `Error 15 SEND_DATA_TOO_LARGE`**
- 解法是強制走完整 `reset → 退回 Loader → 重新載 firmware` 流程
但這只解決「session 間殘留」,**沒解決「拿到一根插上是 KDP1 legacy 的舊 dongle」這個更基礎的問題**——使用者收到 Kneron 出貨的 dongle 可能是 KDP1舊版、可能是 KDP2 但版本太舊、可能 firmware 在運送過程被擦掉留在 Loader mode。所有這些情境的共通解法只有一條**升級到 Kneron 官方 KDP2 標準版本**。
目前 visionA-local 沒有任何 UI 暴露「升級 firmware」這個動作使用者只能
1. 自己想辦法找 DFUT.exeWindows-only Qt 工具)
2. 把 dongle 寄回 Kneron 換貨
3. 放棄使用
→ 這違反 v1.2 北極星指標「**5 分鐘內順利跑出第一次推論的比例 ≥ 95%**」——只要使用者拿到不對版本的 dongle5 分鐘永遠達不到。
### 1.2 為什麼現在做
| 觸發因素 | 說明 |
|---------|------|
| Architect 已完成 research plan | `.autoflow/04-architecture/research-kl520-fw-management/` 7 個檔、合計 ~3000 行,已驗證技術可行 |
| 同事 warrenchen 已有雲端版實作可參考 | `gitea/warrenchen/web_academy_prototype/local_service_win`UX 旅程已被驗證 |
| KneronPLUS C API 跨平台可用 | `libkplus.{dll,so,dylib}` 三平台都在現有 bundle 內、增加成本 0KB |
| 使用者明確要求 + 願意翻案 R5-Q9 | 2026-05-24 拍板 A + B 一次做完 |
| 既有 code 已有 70% 邏輯 | bridge.py `handle_connect()` 已可偵測 Loader mode 並 RAM-load firmware缺的只是「持久化升降版」 |
---
## 2. R5-Q9 翻案分析
### 2.1 R5-Q9 原文progress.md 第二輪決策表)
```
| Q9 | 韌體燒錄 flash | **B** 砍掉 |
```
**位置描述**progress.md 「第二輪使用者決策」表格中、Q9 條目2026-04-11 拍板)。行號因 progress.md 多次追加內容會浮動、文件追溯**以決策內容為準、不以行號為準**(早期 Architect research summary `00-research-summary.md` §1.7 與本檔早期版本均引用過 L776 / L854、僅供歷史追溯參考。「Q9 韌體燒錄 flash 砍掉」的決策本身沒有疑義。
### 2.2 當時為何砍
progress.md 沒留下明文理由只標「B 砍掉」。Architect research 推測的 4 個可能原因(待使用者最終確認):
1. visionA-local 定位是「local 推論工具」、不是「dongle 管理工具」,燒 flash 不屬核心使用旅程
2. 燒 flash 有 brick 風險、當時不想對使用者開放
3. 早期 MVP 範圍縮小、把非必要功能延後
4. 既有「load_firmware 到 RAM」邏輯已夠用基本推論KL520 USB Boot 每次重 load、KL720 已預燒 KDP2
### 2.3 現在為何要翻
| 因素 | 說明 |
|------|------|
| 真實痛點 | 2026-04-21 Error 15 經驗證實「舊 firmware = 完全不能用」 |
| 使用者明確要求 | 2026-05-24 拍板 A + B 全做 |
| 範圍可切割 | 只做「升級到內建 KDP2 標準版本」,不做「使用者燒任意 binary」 |
| Architect research 已驗證可行 | 5 人天 MVP、+0KB 安裝包、技術風險可控 |
| 同事雲端版已驗證 UX | warrenchen 雲端網頁 + 本地服務雙進程版已 ship使用者旅程被驗證過 |
### 2.4 範圍切割:避開 Q9 原始擔憂
| Q9 砍掉的 | 本任務不做 | 本任務做 |
|----------|-----------|---------|
| 「使用者按按鈕燒任意 model 到 device flash」 | ✅ 不做(與 model load 區隔) | — |
| 「開放使用者選任意 binary 寫 flash」 | ✅ 不做(只允許內建 bundle 過的官方 firmware | — |
| — | — | ✅ 偵測 dongle 當前 FW 版本 |
| — | — | ✅ 升級到內建 Kneron 官方 KDP2 標準版本 |
| — | — | ✅ 切換到內建其他 bundle 版本(含降版) |
**既有 `server/internal/flash/` 模組保持「load model 到 device RAM」原意**;新建 **`server/internal/firmware/`** 模組做升降版Architect research §2.4 已明示模組劃分)。
### 2.5 決策痕跡
Architect 已於 [`ADR-001-firmware-management.md`](../../04-architecture/adr/ADR-001-firmware-management.md) 留下完整翻案理由與技術決策Status: Accepted、2026-05-24。本 feature 文件 + ADR-001 + progress.md 三處互相引用、確保未來回溯時不會誤會「為什麼第二輪砍了又補回來」。
---
## 3. 範圍切割A / B 兩階段
### 3.1 A 階段MVPFW 偵測 + 自動升級 KDP1 → KDP2
**裝置範圍**KL520 + KL720既有 driver 已支援)
**功能範圍**
1. **被動偵測**scan / connect 時讀取 firmware 字串、Devices 頁顯示 FW 健康度 badge綠 = 最新、黃 = 可升、紅 = 必升)
2. **主動升級**(單一動作):使用者按「升級到最新」按鈕 → bridge.py 走 `kp.core.update_kdp_firmware_from_files` → progress 透過 WebSocket 推播 → 完成後自動 rescan
3. **不做手動降版 UI**B 階段才做)
**API 範圍**
- `GET /api/devices/:id/firmware`(讀取 FW 狀態)
- `POST /api/devices/:id/firmware/upgrade`(觸發升級)
- WebSocket room `firmware:<deviceId>`progress 推播)
**安裝包衝擊**+0KBKL520/KL720 firmware 已 bundle 在 `server/scripts/firmware/`
**工時**5 人天M9-1 ~ M9-5見 §10
### 3.2 B 階段(擴展):手動降版 + KL630/KL730
**裝置範圍擴展**+ KL630 + KL730需先擴 driver 處理 product_id 0x0630 / 0x0730 + .tar firmware
**功能範圍**
1. **手動降版 UI面向一般使用者**Settings → 「韌體管理」面板,不只 dev mode含多層 safety net見 §4
2. **多版本 firmware 並存**:每個 chip 提供 current + 1-2 個降版選項
3. **KL630/KL730 完整 FW 升降版**:含 .tar firmware 解壓邏輯Architect M9-6 SDK 驗證待完成)
4. **KneronPLUS SDK 對 KL630/KL730 的 Python API 驗證**M9-6
**API 範圍**
- `GET /api/devices/:id/firmware/versions`(列出可選版本)
- `POST /api/devices/:id/firmware/downgrade`(觸發降版,需 `confirmToken: "DOWNGRADE"`
**安裝包衝擊**+7MB保守 bundle 策略;見 §6
**工時**10.5 人天M9-6 ~ M9-13見 §10
### 3.3 A / B 範圍對照表
| 項目 | A 階段MVP | B 階段(擴展) |
|------|---------|---------------|
| **裝置範圍** | KL520 + KL720 | + KL630 + KL730 |
| **操作範圍** | 自動升級 KDP1 → KDP2 | + 手動降版 + 多版本選擇 |
| **使用者介面範圍** | Devices 頁 FW badge + 升級按鈕 + progress modal | + Settings → 韌體管理面板 + 二次確認 modal |
| **新增 API 數** | 3 個GET firmware、POST upgrade、WS progress room | + 2 個GET versions、POST downgrade |
| **bridge.py 新 handler** | `firmware_upgrade` | + `firmware_downgrade` + `firmware_list_versions` |
| **driver 新 method** | `UpgradeFirmware()` | + `DowngradeFirmware(version)` + `ListFirmwareVersions()` + `GetCurrentFirmwareVersion()` |
| **目錄結構** | 沿用 A 階段 `firmware/<chip>/fw_*.bin` | 改 selecting C`firmware/<chip>/{v2.2.0,v2.1.0,kdp1}/` + `CURRENT_VERSION` |
---
## 4. User Stories面向「飛 firmware 痛點」的使用者旅程)
### US-FW-1A 階段 — 拿到舊 dongle 一鍵變可用)
**身份**P1 Arthur內部 FAE/ P2 Dora外部開發者
**情境**:客戶現場、剛拿到 Kneron dongle可能是 KDP1 legacy / 舊 KDP2插上 USB
**敘述**
> 身為 FAE我希望插上 dongle 後 Devices 頁立刻告訴我「這根 firmware 太舊、按下『升級到最新』就能用」,按下後 30 秒~3 分鐘內升級完成、自動 rescan、就能繼續正常 demo。
**驗收標準**
- **AC-FW-1.1**scan 後 Devices 頁卡片右上角顯示 FW badge綠/黃/紅/灰 四色(綠 = 與內建 bundle current 相同;黃 = 比 current 舊但可升、含 v2.1.0 等 older 版本;紅 = legacy KDP1 系列或損毀 firmware 字串讀不到、必須升才能用;**灰 = 狀態未知**:壞掉 firmware / loader mode / KL630/KL730 A 階段「升降版尚未支援」狀態。Design v2.2 §4.2 標 3 色 + 補灰色 = 4 種總狀態。Driver 層判定來源:`firmwareIsLegacy` / `firmwareCanUpgrade` / `bundledFirmwareVersion`Architect TDD §3.1 衍生欄位)
- **AC-FW-1.2**:黃 / 紅 badge 點擊或卡片內「升級到最新」按鈕,跳出 progress modal全程顯示**階段(採 Design 命名preparing準備中 / Preparing/ loading載入引導程式 / Loading loader/ flashing寫入韌體 / Flashing firmware/ verifying驗證中 / Verifying/ done完成 / Done**+ progress bar + 不可中斷警告。WebSocket event 的 `stage` enum 值與 i18n key 與此命名一致Architect TDD §4.3 stage 列舉同步、為 source of truth
- **AC-FW-1.3**:升級成功後 modal 顯示 ✅ + 「裝置已升級到 v2.2.0」 + 自動關閉 modal5 秒後)+ 觸發 Devices 頁 rescan + 卡片 badge 變綠
- **AC-FW-1.4**:升級失敗時 modal 顯示明確失敗類型Design v2.2 §7.1 列 8 種scan / connect / loader / upgrade / verify / timeout / disconnect / 部分成功)+「複製錯誤訊息」按鈕 + 「重新插拔裝置後重試」指引;後端透過 `FirmwareProgress.reason` 細分 stageArchitect TDD §3.4 對應表)
- **AC-FW-1.5**:升級期間 device 進入 `StatusUpgrading` 狀態(既有 driver Status enum 擴展),鎖住其他操作(推論 / 切模型 / disconnect
- **AC-FW-1.6**:升級成功後 device 會 re-enumerateUSB 拔插效果bridge.py 必須等 **5-8 秒(實測 5 秒已穩、保留上界容忍)** 讓 USB stable 才主動 rescan避免 KL520 reset bug 同樣坑progress.md「2026-04-21 推論 bbox」紀錄已驗證機制
- **AC-FW-1.7**KL520 升級預估 ~30 秒(實測值)/ KL720 預估 ~180 秒實測值progress modal 顯示預估時間讓使用者不焦慮。**timeout 護欄上界**KL520 ≤ 60s / KL720 ≤ 200s§7.2 護欄、超過視為失敗)
- **AC-FW-1.8**升級流程屬「device 層」失敗、不應觸發 `watchServer` Error state與 Architect TDD v2.2 §8.1 解耦research §2.1
- **AC-FW-1.9(吸收 A-MID-1 + Architect §2.5**:升級 / 降版進行中、Wails 控制台關閉視窗動作必須被擋下(防止 SIGTERM 中斷 firmware task brick 裝置UI 顯示 modal「韌體切換進行中device X、為避免裝置損毀、無法關閉應用程式」、modal 不可 dismiss、等 firmware task 完成才能關 appArchitect TDD §8.6「graceful shutdown 拒絕」實作 + Design control-panel.md 補對應 modal
### US-FW-2aB 階段 — 一般使用者主動切版本,相容性 / 回上版情境)
**身份**P1 / P2 — 一般使用者FAE / 外部開發者,非純末端 consumer
**情境**(中、低頻率):
- 使用者升版後發現「我的舊 model 在新 FW 上跑不出結果」想回到 v2.1.0
- 使用者跟某個 third-party tool 不相容、要回 KDP1
- 使用者誤觸升級、想 revert
- 客戶現場 demo 需求特定版本
**敘述**
> 身為一般使用者,我希望能去 Settings → 「韌體管理」面板,看到我每根 dongle 當前 FW 版本、bundle 內所有可選版本、每個版本的說明,能選一個並按下「切換到此版本」。我不希望點錯按鈕就 brick 裝置——應該要有明確警告 + 二次確認字串。
### US-FW-2bB 階段 — 進階使用者跨版本切換,測試 / 開發情境)
**身份**P2 — 進階使用者 / 開發者
**情境**
- 開發者測試多版本相容性
- 測試環境需要特定版本
- 「就是想試試看」
**敘述**
> 身為開發者,我希望同一個「韌體管理」面板讓我自由在 bundled 版本間切換、UI 不對升 / 降特別 framing方便我快速測試各版本行為。我能接受多一層確認流程作為 brick 防誤觸。
**framing 共識Design + PM 對齊,吸收互審 MJ-D1**
- **UI 文案統一中性**分頁名稱「韌體管理」、按鈕文案「切換到此版本」、warning 強調「切換可能影響相容性 / 不可中斷」、**不用「降版」字眼**(避免「面向一般使用者過於負面」+ 同時涵蓋 US-FW-2b 開發者跨版本切換情境)
- **程式碼 / log / API 內部用語可保留 `downgrade`**API endpoint 仍是 `POST .../firmware/downgrade`、ADR / TDD / log 行為事件名稱保留技術詞(與 PRD §9 Q-FW-3 對齊 Design v2.2 §2.1 立場)
- **「DOWNGRADE」確認字串保留英文字面**:是 API contract、不 i18n 化Architect 互審結論一致)
### US-FW-2 共通驗收標準US-FW-2a + US-FW-2b 適用)
- **AC-FW-2.1**:入口在 Settings → 「韌體管理」面板(**不在 Devices 頁主流程**避免誤觸Architect research 42 §1.2 推薦;分頁順序「一般 / 硬體 / 韌體 / 模型 / 進階」見 Design v2.2 §2
- **AC-FW-2.2**:列出所有偵測到的 dongle、每張一張卡片顯示dongle 名稱、kn_number、當前 FW 版本、bundle current 版本
- **AC-FW-2.3**:卡片內「切換 FW 版本」accordion 展開後顯示版本 **radio list 或同等選擇 UI**(不限 dropdown — Design v2.2 §3.3 採 radio list理由版本 < 3 a11y 友善每個版本顯示 displayNamev2.2.0 (current)」「v2.1.0 (older)」「KDP1 (legacy)」)+ 說明文案 + 預估時間
- **AC-FW-2.4**選了非當前版本後,「切換到此版本按鈕變紅色destructive 視覺即使是切換到 newer 版本也統一處理點擊後跳出二次確認 modal
- **AC-FW-2.5**二次確認 modal 必含以下警告語Design Agent 定稿文案
- 降版可能導致現有 model 無法運作
- 降版過程不可中斷否則裝置可能損壞
- 降版完成後可能需要重新插拔裝置
- 請確認版本相容性降版至 KDP1 的舊版會限制可用功能
- **AC-FW-2.6**二次確認 modal 強制使用者**輸入字面字串DOWNGRADE」**才能點確認按鈕防誤觸input 欄空 / 不對時按鈕 disabled
- **AC-FW-2.7**二次確認 modal 不可被點外部關閉必須點取消明確關閉確認後 modal 不關閉直接切進行中狀態避免使用者誤以為什麼都沒發生
- **AC-FW-2.8**降版進行中、「進行中UI **不顯示「取消」按鈕**降版不可中斷顯示 persistent banner請勿拔除裝置
- **AC-FW-2.9**API 層強制要求 request body `confirmToken: "DOWNGRADE"`字面字串沒帶 / 帶錯 400 CSRF + 強制 UI 二次確認流程
- **AC-FW-2.10**Driver safety guards
- 拒絕跨晶片誤匹配version 必須在 `ListFirmwareVersions(chip)` 結果內
- 拒絕升版偽裝目標版本 >= current → 拒絕、改走 upgrade API
- 拒絕 no-op目標版本 == current → 拒絕)
- 拒絕 status busydevice 在 `StatusInferencing` / `StatusFlashing` / `StatusUpgrading` 不接受降版)
### US-FW-3B 階段 — KL630/KL730 dongle 偵測 + 升降版)
**身份**P1 / P2
**情境**:客戶用 KL630 或 KL730新一代 chip插上後希望也能偵測 + 升降版
**敘述**
> 身為使用者,我希望 KL630/KL730 跟 KL520/KL720 一樣支援 FW 偵測 + 升降版UI 流程一致。
**驗收標準**
- **AC-FW-3.1**KL630/KL730 dongle 在 Devices 頁能被偵測(既有 driver `handle_connect()` 必須先擴展處理 product_id 0x0630/0x0730progress.md 已標註)
- **AC-FW-3.2**KL630/KL730 的 FW 升降版 UI 流程與 KL520/KL720 完全一致(複用同一套元件)
- **AC-FW-3.3**bridge.py 必須能處理 .tar firmwareArchitect M9-6 弱驗證確認「策略 Z 直接餵 .tar 給 SDK 不可行」、唯一可行解為 **策略 Ybuild-time 解壓 .tar 找 .bin**;詳見 §8.3 + research 41 §4.4
- **AC-FW-3.4**升降版預估時間KL630/KL730 ~60 秒(待 M9-10 強驗證實測校正)
#### AC-FW-3.5KL630/KL730 升降版 — **延後到 B 階段 M9-10 才實作**
**A 階段對 KL630/KL730****只做 FW 偵測**顯示版本字串、Devices 頁 badge 可顯示「未知 / 待 M9-10」灰色 state**不開放升降版動作**(無升級按鈕、無「切換 FW 版本」accordion
**B 階段 M9-10 才實作升降版**,理由(吸收 Architect M9-6 弱驗證結論,詳見 `research-kl520-fw-management/55-m9-6-weak-validation-result.md`
1. **無 warrenchen reference 實作**warrenchen 對 KL630/KL730 完全沒寫 `/firmware/legacy-upgrade/kl630|730` endpoint、bridge.py 對 KL630/KL730 升降版要自己根據 KneronPLUS SDK 推design risk 高)
2. **KneronPLUS wheel 三平台版本不一致**macOS/Linux 是 2.0.0、Windows 是 3.1.2、A 階段要開 KL630/KL730 升降版必先處理三平台 wheel 統一(額外 1-1.5 人天 + KL520/KL720 regression 風險)
3. **無實機 verify 路徑**A 階段不適合冒進、B 階段 M9-10 啟動時 KL630/KL730 實機已就位再驗 `update_kdp_firmware_from_files` 對 KL630/KL730 是否走同一條 flash 寫入路徑
**生效條件**Architect 互審補充、M9-10 啟動前評估):以下任一條件成立 → M9-10 KL630/KL730 升降版可進入;任一條件不滿足 → 維持「只做 FW 偵測 / 不開升降版」:
- **條件 a**KneronPLUS Python wheel 對 product_id 0x0630/0x0730 有 `kp.core.update_kdp_firmware_from_files` 的 dispatch或 ctypes-level `lib.kp_update_kdp_firmware_from_files` 對 KL630/KL730 確認可用)
- **條件 b**:策略 Ybuild-time 解壓 .tar → 取得 `extracted/fw_scpu.bin` / `fw_ncpu.bin`)可正常 produce 兩個 .bin 路徑、且 SDK 接受餵這兩個 .binM9-8 已驗)
- **條件 c**升級驗證階段、firmware 字串可穩定回讀(與 KL520/KL720 相同機制)
任一條件不成立 → KL630/KL730 維持「只做 FW 偵測 only」、UI 顯示版本字串但無升降版動作 + 卡片標「升降版即將支援、目前僅顯示版本資訊」提示。最終決定回 Orchestrator 派 PM 微調 PRD見 §14.3 O-FW-2
---
## 5. 手動降版面向一般使用者user research 假設
### 5.1 為什麼不藏 dev mode
使用者在 2026-05-24 明確決定「手動降版面向一般使用者」、不只 dev mode。理由PM 推測 + 與使用者對話確認):
| 假設 | 支持證據 |
|------|---------|
| H1一般使用者也會遇到「model 在新 FW 上跑不出結果」 | progress.md L93 Error 15 經驗已暗示 firmware 版本對推論結果有影響 |
| H2visionA-local 的目標使用者P1 FAE、P2 開發者)技術水平夠高,能讀懂警告 | R5 Persona 定義 P1 是 FAE、P2 是「外部開發者」,都不是純末端 consumer |
| H3藏在 dev mode 反而會讓真正需要降版的人找不到 | 內部 FAE 找不到 = 客戶現場 demo 失敗 |
| H4safety net二次確認 + 字面字串 + 警告語)足以擋住 90% 誤觸 | Architect research 42 §6 風險矩陣評估後殘餘風險低 |
### 5.2 user research 待驗證項
| # | 項目 | 驗證方式 | 階段 |
|---|------|---------|------|
| UR-1 | 一般使用者是否會誤把「切換 FW 版本」當無害操作 | Beta 測試或 5 人 usability test | B 階段開發完成後 |
| UR-2 | 二次確認字串「DOWNGRADE」是否足以擋誤觸 | 同上 | B 階段開發完成後 |
| UR-3 | 「降版」這個詞是否會嚇跑使用者 | A/B 測試「切換 FW 版本」vs「降版」文案 | B 階段開發完成後 |
| UR-4 | brick 事件發生率(殘餘風險實測) | 上線後 6 個月追蹤客服回報 | Post-launch |
→ B 階段上線時、UR-1/UR-2/UR-3 視機會做小規模測試UR-4 是長期追蹤項。
### 5.3 情境分析
Architect research 42 §1.1 列出 5 個一般使用者會降版的情境(中、低頻率):
| 情境 | 頻率 | 處理 |
|------|------|------|
| 「我的舊 model 在新 FW 上跑不出結果」 | 中 | 提供降版回 v2.1 選項 |
| 「跟某個 third-party tool 不相容」 | 低 | 提供降版回 KDP1 選項(僅 KL520 |
| 「我升錯了、想回到原本狀態」 | 低 | 提供「降版回上次版本」選項 |
| 「測試環境需要特定版本」 | 中 | 提供降版到任意 bundled 版本 |
| 「就是想試試看」 | 中 | 用警告語勸阻、但不阻止 |
---
## 6. Bundle 策略與安裝包衝擊
### 6.1 使用者拍板的保守策略
| Chip | current | 額外 bundled | 合計(每 chip|
|------|---------|------------|--------------|
| KL520 | v2.2.0 (~100KB) | v2.1.0 (~100KB) + kdp1 (~90KB) | ~290KB |
| KL720 | v2.2.0 (~250KB) | v2.1.0 (~250KB) | ~500KB |
| KL630 | SDK-v2.5.7 (~3MB) | + extracted (~3MB) | ~6MB |
| KL730 | SDK-v1.3.0 (~4MB) | + extracted (~4MB) | ~8MB |
| **合計** | | | **~15MB**(保守估計),實際 ~7MB因 KL630/KL730 解壓策略未定,可能不需 extracted |
### 6.2 多版本目錄結構(選項 C
使用者拍板選 C — `firmware/<chip>/{v2.2.0,v2.1.0,kdp1}/` + `CURRENT_VERSION` 單行檔Architect research 42 §3.2 / §3.3)。
理由:
- 跨平台無 symlink 風險vs 選項 A symlink
- 節省空間vs 選項 B 實體副本)
- 架構乾淨清晰
### 6.3 安裝包大小衝擊
- 既有 dmg163MB
- A 階段:+0KB → 163MB
- B 階段(保守):+7MB → **~170MB**
→ 在 PRD v2.1 §6.2 「macOS dmg 目標 ≤ 185MB / 上限 ≤ 220MB」範圍內無需 PRD §6.2 數字調整。
**使用者體驗層面**(吸收 Design P-LOW-2+7MB 對下載 / 安裝時間影響:寬頻 ~50MB/s → +0.14 秒(無感)/ 一般 4G hotspot ~5MB/s → +1.4 秒(無感)/ 慢速 wifi ~1MB/s → +7 秒(有感但可接受、屬罕見場景)
### 6.4 不做線上更新通道
使用者拍板「不做線上更新通道、所有 firmware 內嵌」progress.md 2026-05-24
→ 不實作 OTA / 不做 firmware 從遠端 fetch。所有可用版本就是 bundle 內的版本。
→ 風險:未來 Kneron 出新 firmware 版本時必須打新安裝包才能用(接受此 trade-off因為使用者明確要 offline-first
---
## 7. 成功指標
### 7.1 主要指標(與 PRD v2.1 §1.4 北極星指標掛鉤)
| 指標 | baseline | A 階段目標 | B 階段目標 |
|------|---------|-----------|----------|
| **5 分鐘首次推論達成率**PRD v2.1 北極星)| 假設受 firmware 問題影響 ~10% | **+ 5pp**(從「拿到舊 dongle 完全不能用」變「+ 30 秒升級即可用」) | 維持 |
| **拿到舊 dongle 後完成首次推論的中位時間** | 不可估算(需重新出貨)| **≤ 5 分鐘**(自動升級流程內) | 維持 |
### 7.2 次要指標
| 指標 | 目標 | source |
|------|------|--------|
| FW 升級成功率A 階段KL520 + KL720| ≥ 95% | log 統計(非自動 telemetry、技術支援彙整|
| FW 降版成功率B 階段KL520 + KL720| ≥ 95% | 同上 |
| FW 升降版平均時長(護欄)| KL520 ≤ 60s / KL720 ≤ 200s / KL630/KL730 待 M9-10 強驗證校正 | log 統計 |
| 一般使用者誤觸降版發生率B 階段上線後 3 個月)| ≤ 1% | 客服回報統計 |
| Brick 事件B 階段上線後 6 個月) | ≤ 0.1%< 1 / 1000 dongles | 客服回報 |
**注意(吸收 Architect §1.2**v2.2 階段大部分 FW 指標**靠客服回報 + log 統計非自動上報**自動 telemetry 是未來 feature不在本 PRD scope
### 7.2.1 體驗指標(吸收 Design P-MID-1
以下指標補強 §7.2 純技術指標量測使用者體驗層面是否健康」:
| 指標 | 目標 | source / 量測方式 |
|------|------|------|
| **升級任務完成率**modal 開啟 升級成功 toast| 85% | log 統計modal-opened 事件 vs upgrade-success 事件配對|
| **二次確認 modal 中途放棄率**B 階段降版 | 50-70%合理區間| log 統計confirm-modal-shown vs token-typed-and-confirmed 配對|
| **Devices 頁 FW badge 點擊率**只算紅 / badge| 30% | 前端 click 事件統計 |
| **升級失敗後重試率**首次失敗後 5 分鐘內重試比例| 視底線追蹤即可 | log 統計 |
| **B 階段 SUS 分數**5 usability test| 65 | Beta 階段 usability test §5.2 UR-1~3 |
**解讀準則**
- 二次確認中途放棄率 < 50% 暗示UX 不夠恐嚇」(應加強警告
- 二次確認中途放棄率 > 70% 暗示「嚇跑使用者」(應減弱警告)
- FW badge 點擊率 < 30% 暗示使用者沒注意到要升級」(應加強顯著性 / IA
### 7.3 護欄指標(不可惡化)
| 指標 | 上限 |
|------|------|
| dmg 安裝包大小 | 220MBPRD v2.1 §6.2 上限|
| FW 升降版期間 server 是否進 Error state | 不可device 層失敗 server 解耦|
| FW 升降版期間其他 device 是否能正常推論 | 可以device 之間互不影響|
| 啟動時間 | 60 PRD v2.1 AC-1.3FW 升降版不在啟動 pipeline 無影響|
---
## 8. 風險與已知限制
承前 Architect research 30 + 40 + 41 + 42 的風險清單PM 視角彙整為 **R-FW-1 ~ R-FW-12**不重寫技術細節引用 research)。
### 8.1 R-FW-1 ~ R-FW-7A + B 階段共通,來自 Architect research 30
| ID | 風險 | 可能性 | 影響 | 等級 | 緩解 | 詳見 |
|----|------|-------|------|------|------|------|
| R-FW-1 | KL520 reset bug 再現升級後 device re-enumerate 不穩定| | | P2 | 升級後等 5-8 + 主動 rescan承襲 2026-04-21 修法 | research 30 §3 |
| R-FW-2 | KneronPLUS Python wheel 版本對 update API 支援度不足 | | | P1 | **M9-6 弱驗證已確認** 3.1.2 wheel `update_kdp_firmware_from_files` 完整支援warrenchen 使用中)、 macOS/Linux 2.0.0 wheel enum 35 分鐘強驗證策略 Y解壓 .tar .bin唯一可行解 | research 30 §4 + 40 §5 + **55-m9-6-weak-validation-result.md** |
| R-FW-3 | bridge.py `kp.core.update_kdp_firmware_from_files` macOS x86_64 行為未驗證 | | | P2 | **M9-6 弱驗證**API 簽名與 warrenchen 一致預期 macOS/Linux 2.0.0 + Windows 3.1.2 KL520/KL720 升級可用M9-1 開發前 backend agent 35 分鐘強驗證 enum 不存在則升 wheel牽動三平台 wheel 統一 | research 30 §4 + **55-m9-6-weak-validation-result.md** |
| R-FW-4 | 升級 timeout 設定不合理太短 = 誤判失敗、太長 = UI| | | P3 | warrenchen 經驗值KL520 30s / KL720 180s+ progress 推播提供使用者感知 | research 30 §5 |
| R-FW-5 | 打包 Kneron 官方 firmware 是否合法 R5-B4 預置模型授權同性質| | | **P0**發佈 gate| 使用者明示先不管授權發佈前再評估」、PRD 標註為未解決問題(§9| research 00 §1.7 + 40 §7 + 42 §7 |
| R-FW-6 | 既有 `flash/` 模組名稱混淆load model RAM vs firmware| | | P3 | 新建 `firmware/` 模組保持 `flash/` 原意Architect research §2.4| research 00 §2.4 |
| R-FW-7 | 升級失敗 device 進入 unknown state既不能用舊 firmware firmware 也沒寫成功| | | P1 | bridge.py 失敗時不切換 device.firmware 字串UI 提示重新插拔Plan B技術支援 SOP DFUT.exe 救磚不打包進 app | research 30 §6 + 42 §6.3 |
### 8.2 R-FW-8 ~ R-FW-12B 階段新增,來自 research 40 + 42
| ID | 風險 | 可能性 | 影響 | 等級 | 緩解 | 詳見 |
|----|------|-------|------|------|------|------|
| R-FW-8 | KneronPLUS SDK KL630/KL730 API 行為不可預測 | | | P1 | M9-6 SDK 驗證 A 階段平行進行progress.md 2026-05-24 拍板| research 40 §5 |
| R-FW-9 | .tar 解包對安裝包大小衝擊如果採策略 X build-time 解壓 + bundle| | | P3 | 採策略 Y Z 平衡空間 vs 速度M9-6 結論定| research 41 §3 |
| R-FW-10 | KL630/KL730 沒有 Loader mode 概念 KL520 USB Boot 流程不同| | | P2 | bridge.py `handle_connect()` 必須 chip-aware 分流既有 fall-through KL520 bug會連不上| research 40 §3 |
| R-FW-11 | 一般使用者誤觸降版導致 brick | | | **P1** | 多層 safety netUI 警告 + 二次確認字串 + driver guard + 進行中 bannerresearch 42 §56 + 本檔 AC-FW-2.5 ~ 2.10| research 42 §6 |
| R-FW-12 | 多版本管理 UX 複雜度使用者看不懂 v2.2.0 vs v2.1.0 vs KDP1| | | P2 | **已具體落地**Design v2.2 §3.3 accordion + radio list + 每個版本 displayName 後綴current/older/legacy+ §9 i18n 涵蓋KDP1 額外紅色警告 banner | research 42 §5.3 + Design v2.2 §3.3 / §9 |
| **R-FW-13** | **KneronPLUS wheel 三平台版本不一致**macOS/Linux 2.0.0 vs Windows 3.1.2| | | **P1** | **A 階段**先在 macOS/Linux 強驗證 2.0.0 wheel 是否含 KL520/KL720 update APIM9-1 啟動前 35 分鐘)、預期可用若不可用先升 Windows 對齊**B 階段 M9-10 啟動前必須升 macOS/Linux 3.1.2** KL630/KL730 enum+ KL520/KL720 三平台 E2E 回歸M9-13 | **55-m9-6-weak-validation-result.md** 發現 6 |
| **R-FW-14**Frontend 防誤觸補強 | 使用者輸入downgrade小寫繞過確認 | | | P2 | Frontend 用嚴格 `===` 比對、**不用 `.toUpperCase()`**後端 API 同時雙重比對M9-12 Reviewer 必檢查 | Design v2.2 §12.2 R-FW-11.5 自提 + Architect §2.10 同意 |
### 8.3 與既有架構的衝突已釐清項
| 衝突點 | 結論 | 詳見 |
|--------|------|------|
| **watchServer Error state**TDD v2.1 §8| FW 升降版失敗屬 device server watchServer 解耦不觸發 Error state | research 30 §2.1 |
| **R5-E 60s 啟動上限** | FW 升降版是使用者主動觸發不在啟動 pipeline 無關 | research 30 §2.3 |
| **KL520 reset bug fix**2026-04-21| 升級成功後 device re-enumerate 必須等 5-8 + 主動 rescan不立即 reconnect | research 30 §2.2 |
| **既有 `flash/` 模組命名包袱** | 不改檔名本任務範圍外)、新文件命名用 `kneron_*` `device_firmware_*` | research 30 §2.5 |
---
## 9. 未解決問題(彙整給 Orchestrator
| # | 問題 | 性質 | 處理建議 |
|---|------|------|---------|
| Q-FW-1 | Kneron firmware redistribution 授權含舊版 v2.1.0 / KDP1 | **發佈前 gate** R5-B4 預置模型授權同性質| 使用者明示先不管授權發佈前再評估」,PRD 留紀錄建議發佈前 3-6 個月與 Kneron 取得明確書面授權授權範圍含 current + 舊版v2.1.0 / KDP1+ KL630/KL730 firmware tar |
| Q-FW-2 | KneronPLUS Python wheel KL630/KL730 update API 支援度 | **B 階段啟動 gate** | M9-6 SDK 驗證為先 A 階段平行)、結論定 B 階段 scope若不支援AC-FW-3.5 啟動降級為 FW 偵測 only |
| Q-FW-3 | 降版這個詞是否用於 UI 文案 | ** 已決定吸收三方互審 MJ-D1** | UI 文案統一中性分頁名稱韌體管理」、按鈕切換到此版本」),**不用降版字眼**程式碼 / log / API 內部用語可保留 `downgrade`API endpoint 仍是 `POST .../firmware/downgrade`對齊 Design v2.2 §2.1 + Architect 同意 |
| Q-FW-8| DOWNGRADE確認字串是否 i18n | ** 已決定吸收 Design D-M3 + Architect §2.2** | 保留英文字面 `"DOWNGRADE"` API contract i18n UI 提示文字 i18n 請輸入 DOWNGRADE 確認中文 + Type DOWNGRADE to confirm英文 input 比對的字串跨語系一致 |
| Q-FW-4 | 一般使用者降版的 user research 假設驗證時機 | **B 階段 post-launch** | UR-1/UR-2/UR-3 Beta 階段做 5 usability testUR-4 brick 事件追蹤 6 個月(§5.2|
| Q-FW-5 | KL520 / KL720 / KL630 / KL730 升降版預估時間是否準確 | **開發階段實測** | M9-5A/ M9-13B三平台實機驗證時校正 |
| Q-FW-6 | progress.md R5-Q9 行號 L776 vs L854 不一致 | ** 已決定** | 文件追溯以progress.md 第二輪使用者決策 Q9 條目描述式引用為準不引用行號行號因 progress.md 多次追加會浮動)。決策本身明確2026-04-11 第二輪 Q9 韌體燒錄 flash B 砍掉」、 PRD §2.1 已修正 |
| Q-FW-7 | 升級失敗後的救磚 SOP是否需要在 UI 內提示 | **B 階段 Design 決定** | 目前傾向UI 提示請重新插拔裝置後重試」+「複製錯誤訊息」+ 技術支援聯絡資訊research 42 §6.3 SOP 留內部 wiki|
---
## 10. 工時與 Milestone
### 10.1 A 階段M9-1 ~ M9-5、共 5 人天PM 拆法、Architect 互審同意採此版本)
| # | Milestone | 工時 | 依賴 | 平行性 |
|---|-----------|------|------|-------|
| M9-0 | 開發前強驗證backend agent35 分鐘macOS/Linux `python3 -c "import kp; print(kp.ProductId.KP_DEVICE_KL630)"`判斷 2.0.0 wheel 是否含 KL630/KL730 enum + `tar -tvf` inspect firmware .tar | < 0.1 人天內含| | M9-1 之前必跑 |
| M9-1 | bridge.py 新增 `firmware_upgrade` handlerKneronPLUS C API策略 Y 唯一可行解| 1 人天 | M9-0 | 獨立 |
| M9-2 | Go driver + service`UpgradeFirmware()` + `server/internal/firmware/service.go` + safety guards | 1 人天 | M9-1 | |
| M9-3 | API handler + WebSocket progress room `FirmwareProgress.reason` 細分 stageElapsed/ETA 欄位graceful shutdown 拒絕邏輯 hook | 0.5 人天 | M9-2 | |
| M9-4 | 前端 Devices FW badge4 色含灰色狀態未知+ 升級按鈕 + progress modal + 6 component-level design tokens 落地 a11y 對比驗證| 1.5 人天 | M9-3 | M9-1/M9-2/M9-3 部分平行mock API|
| M9-5 | 三平台實機驗證macOS / Windows / Linux × KL520 + KL720 完整升級 E2E| 1 人天 | 全部前置完成 | |
| **A 合計** | | **5 人天** | | |
### 10.2 B 階段M9-6 ~ M9-13、共 10.5 人天PM 拆法、Architect 互審同意採此版本)
| # | Milestone | 工時 | 依賴 | 平行性 |
|---|-----------|------|------|-------|
| M9-6 | KneronPLUS SDK KL630/KL730 + .tar firmware Python API 驗證**弱驗證已完成** `55-m9-6-weak-validation-result.md`強驗證須等 KL630/KL730 實機| 1 人天含弱驗證 0.5 + 強驗證 0.5| | **與 A 階段平行**2026-05-24 使用者決策|
| M9-7 | Driver 擴展處理 product_id 0x0630/0x0730 + chip-aware connect 分流 KL630/KL730 firmware 載入分支| 1.5 人天 | M9-6 | |
| M9-8 | bridge.py 處理 .tar firmware**策略 Y 唯一可行解build-time 解壓**策略 Z 已被弱驗證排除| 1.5 人天 | M9-7 | |
| M9-9 | 多版本目錄結構重整A 階段檔案搬到 `<chip>/v2.2.0/` + `CURRENT_VERSION`+ bridge.py 升級 `_resolve_firmware_paths_versioned()` | 1 人天 | A 階段完成 | |
| M9-10 | **KL630/KL730 升級 / 降版 driver method 實作**AC-FW-3.5 生效條件評估在此 milestone 啟動時跑 warrenchen reference 實作design risk 較高| 1.5 人天 | M9-8 + M9-9 + M9-6 強驗證完成 + macOS/Linux wheel 3.1.2R-FW-13| |
| M9-11 | 多版本降版後端API + bridge.py + driver guards + graceful shutdown 拒絕落地| 1.5 人天 | M9-9 | |
| M9-12 | 降版 UISettings 韌體管理面板 + 二次確認 modal + 進行中 UI + Wails 控制台關閉攔截 modal| 2 人天Frontend 1 + Design 1| M9-11 | Design + Frontend 平行 |
| M9-13 | B 階段三平台實機驗證 + KL520+KL720 wheel 升級 regression + Beta usability testUR-1/UR-2/UR-3| 1 人天 | M9-7 ~ M9-12 全部 | |
| **B 合計** | | **10.5 人天** | | |
### 10.3 合計
- A + B = **15.5 人天**
- Architect research 結論一致
---
## 11. 涉及檔案 / 模組(從 Architect research 30 + 40 摘要)
### 11.1 新建模組
```
server/internal/firmware/ ← 新模組(升降版核心)
├── service.go ← FirmwareService 提供 Upgrade/Downgrade/List
├── versions.go ← 版本管理 + 比較邏輯isOlderVersion()
└── safety.go ← driver guard helpers不跨晶片 / 不升版偽裝 / 不 no-op
```
### 11.2 既有檔案修改
| 檔案 | 修改範圍 | 階段 |
|------|---------|------|
| `server/scripts/kneron_bridge.py` | 新增 handler`firmware_upgrade` / `firmware_downgrade` / `firmware_list_versions` | A + B |
| `server/internal/driver/kneron/kl720_driver.go` | 新增 method`UpgradeFirmware` / `DowngradeFirmware` / `ListFirmwareVersions` / `GetCurrentFirmwareVersion` | A + B |
| `server/internal/driver/types.go` 或同等 | DeviceDriver interface 擴展 + `FirmwareVersion` / `FirmwareProgress` struct | A |
| `server/internal/api/handlers/device_handler.go` 或新檔 | endpoint`GET /api/devices/:id/firmware*` / `POST .../upgrade` / `POST .../downgrade` | A + B |
| `server/internal/api/router.go` | 註冊新路由 | A + B |
| `server/internal/ws/hub.go` | 註冊 `firmware:<deviceId>` WebSocket room | A |
| `server/scripts/firmware/` | 重整目錄結構為 `<chip>/<version>/` + `CURRENT_VERSION` | BM9-9|
### 11.3 前端新增 / 修改
| 檔案 | 修改範圍 | 階段 |
|------|---------|------|
| `frontend/components/devices/device-card.tsx` 或同等 | FW badge//+ 升級按鈕 | A |
| `frontend/components/devices/firmware-upgrade-modal.tsx` | progress modal | A |
| `frontend/pages/settings/firmware.tsx` 或同等 | Settings 韌體管理面板 | B |
| `frontend/components/firmware/version-switch-modal.tsx` | 二次確認 modal | B |
| `frontend/components/firmware/downgrade-progress-modal.tsx` | 進行中 UI | B |
| i18n keys | +46 research 42 §5.6 估算 | B 為主 |
### 11.4 文件新增
| 檔案 | 角色 | 階段 |
|------|------|------|
| `docs/autoflow/04-architecture/adr/ADR-001-firmware-management.md` 或同等 | Architect R5-Q9 翻案紀錄 + 技術決策 | A 啟動前 |
| `docs/autoflow/04-architecture/TDD-v2.md` §5.4 firmware 子節 | Architect TDD v2.2 | A 啟動前 |
| `docs/autoflow/03-design/design-spec-v2.md` 對應子節 | Design Agent 補設計規格 v2.2 | A 啟動前 |
| `docs/autoflow/02-prd/features/feature-firmware-management.md`本檔| PM PRD v2.2 | 進行中 |
| `docs/troubleshooting/brick-recovery.md`內部 wiki| 技術支援 SOPDFUT.exe 救磚流程**不打包進 app**| 上線前 |
---
## 12. 與既有 R5 決策的關係
| R5 條目 | 本任務關係 |
|---------|----------|
| **R5-Q9砍 flash** | **翻案**(§2透過範圍切割避開原始擔憂 |
| **R5-B4Kneron 預置模型 redistribution** | 同性質問題擴展 本任務的 firmware bundle R5-B4 同樣是打包 Kneron 智財」、發佈前須一起跟 Kneron 取得授權(§9 Q-FW-1|
| **R5-E60s 啟動 + perceived performance** | 無關 FW 升降版不在啟動 pipeline research 30 §2.3|
| **R5-D1Server 崩潰 OS 通知)** | 不擴展 FW 升降版失敗屬 device 不發 OS 通知 device toast 一致PRD v2.1 §AC-3.7 + R4-8 策略|
| **R5-1產品定位** | 對齊 FW 管理 UI 住瀏覽器 Web UIDevices + Settings 韌體管理)、不住 Wails 控制台 |
| **R5-3砍 tray** | 無衝突 |
| **R5-6ffmpeg LGPL** | 無關 |
---
## 13. 風險:本 feature 對既有功能的影響
承前 R5既有專案的每一步都需要特別小心避免破壞現有功能原則 feature 的潛在影響
| 影響範圍 | 風險 | 緩解 |
|---------|------|------|
| 既有 KL520 / KL720 推論流程 | 升級期間 device 鎖住 `StatusUpgrading`其他操作會被擋 | 預期行為UI 清楚告知 |
| 既有 `flash/service.go` (load model RAM)| 命名 vs `firmware/` 模組可能混淆 | 嚴格保持 `flash/` 原意新模組獨立目錄research §2.4|
| KL630 / KL730 連線既有 fall-through KL520 bug| 本任務 M9-7 必修否則 KL630/KL730 連不上 | M9-7 B 階段必做driver 改動需 Reviewer 把關 |
| 既有 `kneron_bridge.py handle_connect()` | 新增 handler 不影響既有 connect 流程獨立 handler| Architect 確認 |
| 安裝包大小既有 dmg 163MB| +7MB ~170MB仍在 PRD v2.1 §6.2 上限內(≤ 220MB| 已在範圍內無需 PRD §6.2 數字調整 |
---
## 14. 三方互審回饋處理紀錄v2.2 → v2.2.1
### 14.1 給 Design Agent — **全部已處理**
- **D-FW-1**降版入口位置):✅ Design v2.2 §2 Settings 3 分頁韌體管理」、 PM 對齊
- **D-FW-2**(「降版用詞):✅ **已決定**UI 統一中性韌體管理」/「切換到此版本」、不用降版字眼內部 / API / log 保留 `downgrade`Q-FW-3 已落定 §9
- **D-FW-3**防誤觸機制):✅ Design v2.2 §6.1 DOWNGRADE嚴格字面輸入嚴格 `===` 比對不接受小寫 / 全形 / 半形空白雙重保險
- **D-FW-4**FW badge 三色閾值):✅ AC-FW-1.1 已明示 4 色閾值 / / / )、Design v2.2 §4.2 對齊
- **D-FW-5**6 階段中英雙語文案):✅ **採 Design 命名**preparing / loading / flashing / verifying / done / error中文文案準備中 / 載入引導程式 / 寫入韌體 / 驗證中 / 完成 / 失敗)、 AC-FW-1.2
- **D-FW-6**持久 banner 視覺):✅ Design v2.2 §6.3 已落地
### 14.2 給 Architect Agent — **大部分已處理**
- **A-FW-1**R5-Q9 行號):✅ **已決定**本檔 §2.1 改為描述式引用Q-FW-6 已落定
- **A-FW-2**driver safety guards):✅ Architect TDD v2.2 §2.1 + §3.3 已對應寫具體 Go interface + `_validate_downgrade_request`
- **A-FW-3**三平台實機驗證):✅ Architect TDD §11.4 已涵蓋
- **A-FW-4**KL630/KL730 wheel 支援度):✅ **已決定**吸收 M9-6 弱驗證AC-FW-3.5 延後到 B 階段 M9-10 a/b/c 生效條件見本檔對應段落
- **A-FW-5**模組路徑 `server/internal/firmware/`):✅ Architect TDD v2.2 §2.1 對齊
- **A-FW-6** R5-B4 授權合併):✅ Architect ADR-001 §Compliance `[ ] 與 Kneron 取得 firmware redistribution 授權`、§Related 已連結 R5-B4
### 14.3 給 Orchestrator — **追蹤項**
- **O-FW-1** R5-B4 release blocker 合併):⏳ Orchestrator 統一決定PM 建議合併都是 Kneron 智財 + 都是發佈前 gate)、但保留各自具體 scopefirmware vs model 兩個 license 範圍
- **O-FW-2**M9-6 強驗證 + AC-FW-3.5 觸發條件):⏳ M9-10 啟動時評估 a/b/c 三條件任一不滿足 Orchestrator PM 微調 PRDKL630/KL730 維持 FW 偵測 only / 不開升降版
### 14.4 互審 Minor 處理紀錄
| # | 來源 | 內容 | 處理 |
|---|------|------|------|
| M-A1 | Architect TDD §10 R-FW-5 等級待釐清」| 統一用 P0/P1/P2/P3 分級 | Architect TDDPM 不處理|
| M-A2 | Architect TDD §11.3 KL720 timeout 上界測試 | KL720 升級實測時長 200s測試案例 | Architect TDD |
| M-A3 | Architect §3.1 API `notes` / `estimatedDurationSec` 欄位 | 補在 `GET /firmware/versions` response | Architect TDD |
| M-A4 | TDD §6.2 KL520 KDP1 pid=0x0200 vs KL720 衝突 | Architect 確認後對齊 PRD §1.1 | Architect TDDPM 等對齊結果|
| M-D1 | Design §9 i18n keys 52 vs PM 46 | Design 實際值 52 keys | 本檔 §11.3 已記「+46 estimate)→ 實際 52 Design v2.2 §9)」 |
| M-D2 | Design §3.3 accordion + radio listvs PRDdropdown | AC-FW-2.3 radio list 或同等選擇 UI | 已處理 |
| M-D3 | DOWNGRADE 字串 i18n | Q-FW-8 已落定保留英文字面 | 已處理 |
| P-MID-1 | 缺體驗指標 | §7.2.1 體驗指標 5 | 已處理 |
| P-MID-2 | PRD 用詞混用降版 | Q-FW-3 落定 + US-FW-2 a/b + framing 共識段落 | 已處理 |
| P-MID-3 | KL520 升級時間 30s vs 60s | AC-FW-1.7 明示「~30 秒實測 + 60s 護欄上界」| 已處理 |
| P-MID-4 | badge 閾值不清 | AC-FW-1.1 4 色定義含灰色狀態未知| 已處理 |
| P-LOW-1 | 使用者怎麼發現要降版US | 標為 v2.3 未來迭代Workspace inference 失敗時 hint| 暫不處理 |
| P-LOW-2 | Bundle 安裝時間衝擊 | §6.3 補一句 | §6.3 |
| P-LOW-3 | R-FW-12 緩解過抽象 | R-FW-12 已具體落地」+ 引用 Design v2.2 §3.3 / §9 | 已處理 |
| F1-F7 | Architect 自查 7 項必修 | Architect TDDPM 不直接處理 | Architect 端處理中 |
---
## 變更紀錄
| 版本 | 日期 | 作者 | 變更 |
|------|------|------|------|
| v2.2-draft | 2026-05-24 | PM Agent | 初稿翻案 R5-Q9A + B 兩階段範圍定義多層 safety net for 一般使用者降版風險 R-FW-1 ~ R-FW-12 彙整自 Architect research 30/40/41/42;§14 列出 14 Design / Architect / Orchestrator 待互審項 |
| v2.2.1 | 2026-05-25 | PM Agent | 吸收三方互審PM Self / Design / Architect+ M9-6 弱驗證結果。**主要變更**:①stage 命名統一採 Designpreparing/loading/flashing/verifying)②M9 工時表拆法採 PMArchitect 已同意)③AC-FW-3.5KL630/KL730 升降版延後到 B 階段 M9-10補生效條件 a/b/cA 階段 KL630/KL730 只做 FW 偵測無升降版按鈕)④ADR-009 ADR-001 編號統一R5-Q9 行號改描述式引用不引用脆弱行號US-FW-2 拆成 US-FW-2a一般使用者+ US-FW-2b進階使用者)、UI 文案 framing 統一中性韌體管理」「切換到此版本」⑦ §7.2.1 體驗指標 5 升級任務完成率 / 中途放棄率 / badge 點擊率 / 重試率 / SUS 分數)⑧新增 R-FW-13 wheel 三平台版本不一致 + R-FW-14 大小寫繞過 AC-FW-1.9 graceful shutdown 拒絕badge 4 色定義補灰色狀態未知)⑪§14 標記哪些已解決 / 哪些 追蹤中詳見本檔 §14.4 互審 Minor 處理紀錄 |