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>
600 lines
46 KiB
Markdown
600 lines
46 KiB
Markdown
# feature: Kneron Dongle FW 偵測 + 升降版
|
||
|
||
> 對應 PRD:[`PRD-v2.md`](../PRD-v2.md) v2.2(2026-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.exe(Windows-only Qt 工具)
|
||
2. 把 dongle 寄回 Kneron 換貨
|
||
3. 放棄使用
|
||
|
||
→ 這違反 v1.2 北極星指標「**5 分鐘內順利跑出第一次推論的比例 ≥ 95%**」——只要使用者拿到不對版本的 dongle,5 分鐘永遠達不到。
|
||
|
||
### 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 階段(MVP):FW 偵測 + 自動升級 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 推播)
|
||
|
||
**安裝包衝擊**:+0KB(KL520/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-1(A 階段 — 拿到舊 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」 + 自動關閉 modal(5 秒後)+ 觸發 Devices 頁 rescan + 卡片 badge 變綠
|
||
- **AC-FW-1.4**:升級失敗時 modal 顯示明確失敗類型(Design v2.2 §7.1 列 8 種:scan / connect / loader / upgrade / verify / timeout / disconnect / 部分成功)+「複製錯誤訊息」按鈕 + 「重新插拔裝置後重試」指引;後端透過 `FirmwareProgress.reason` 細分 stage(Architect TDD §3.4 對應表)
|
||
- **AC-FW-1.5**:升級期間 device 進入 `StatusUpgrading` 狀態(既有 driver Status enum 擴展),鎖住其他操作(推論 / 切模型 / disconnect)
|
||
- **AC-FW-1.6**:升級成功後 device 會 re-enumerate(USB 拔插效果),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 完成才能關 app(Architect TDD §8.6「graceful shutdown 拒絕」實作 + Design control-panel.md 補對應 modal)
|
||
|
||
### US-FW-2a(B 階段 — 一般使用者主動切版本,相容性 / 回上版情境)
|
||
|
||
**身份**:P1 / P2 — 一般使用者(FAE / 外部開發者,非純末端 consumer)
|
||
|
||
**情境**(中、低頻率):
|
||
- 使用者升版後發現「我的舊 model 在新 FW 上跑不出結果」想回到 v2.1.0
|
||
- 使用者跟某個 third-party tool 不相容、要回 KDP1
|
||
- 使用者誤觸升級、想 revert
|
||
- 客戶現場 demo 需求特定版本
|
||
|
||
**敘述**:
|
||
> 身為一般使用者,我希望能去 Settings → 「韌體管理」面板,看到我每根 dongle 當前 FW 版本、bundle 內所有可選版本、每個版本的說明,能選一個並按下「切換到此版本」。我不希望點錯按鈕就 brick 裝置——應該要有明確警告 + 二次確認字串。
|
||
|
||
### US-FW-2b(B 階段 — 進階使用者跨版本切換,測試 / 開發情境)
|
||
|
||
**身份**: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 友善),每個版本顯示 displayName(如「v2.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 busy(device 在 `StatusInferencing` / `StatusFlashing` / `StatusUpgrading` 不接受降版)
|
||
|
||
### US-FW-3(B 階段 — 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/0x0730,progress.md 已標註)
|
||
- **AC-FW-3.2**:KL630/KL730 的 FW 升降版 UI 流程與 KL520/KL720 完全一致(複用同一套元件)
|
||
- **AC-FW-3.3**:bridge.py 必須能處理 .tar firmware(Architect M9-6 弱驗證確認「策略 Z 直接餵 .tar 給 SDK 不可行」、唯一可行解為 **策略 Y:build-time 解壓 .tar 找 .bin**;詳見 §8.3 + research 41 §4.4)
|
||
- **AC-FW-3.4**:升降版預估時間:KL630/KL730 ~60 秒(待 M9-10 強驗證實測校正)
|
||
|
||
#### AC-FW-3.5(KL630/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**:策略 Y(build-time 解壓 .tar → 取得 `extracted/fw_scpu.bin` / `fw_ncpu.bin`)可正常 produce 兩個 .bin 路徑、且 SDK 接受餵這兩個 .bin(M9-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 版本對推論結果有影響 |
|
||
| H2:visionA-local 的目標使用者(P1 FAE、P2 開發者)技術水平夠高,能讀懂警告 | R5 Persona 定義 P1 是 FAE、P2 是「外部開發者」,都不是純末端 consumer |
|
||
| H3:藏在 dev mode 反而會讓真正需要降版的人找不到 | 內部 FAE 找不到 = 客戶現場 demo 失敗 |
|
||
| H4:safety 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 安裝包大小衝擊
|
||
|
||
- 既有 dmg:163MB
|
||
- 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 安裝包大小 | ≤ 220MB(PRD v2.1 §6.2 上限)|
|
||
| FW 升降版期間 server 是否進 Error state | 不可(device 層失敗、與 server 解耦)|
|
||
| FW 升降版期間其他 device 是否能正常推論 | 可以(device 之間互不影響)|
|
||
| 啟動時間 | ≤ 60 秒(PRD v2.1 AC-1.3,FW 升降版不在啟動 pipeline 內、無影響)|
|
||
|
||
---
|
||
|
||
## 8. 風險與已知限制
|
||
|
||
承前 Architect research 30 + 40 + 41 + 42 的風險清單,PM 視角彙整為 **R-FW-1 ~ R-FW-12**(不重寫技術細節,引用 research)。
|
||
|
||
### 8.1 R-FW-1 ~ R-FW-7(A + 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-12(B 階段新增,來自 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 net:UI 警告 + 二次確認字串 + driver guard + 進行中 banner(research 42 §5/§6 + 本檔 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 API(M9-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 test;UR-4 brick 事件追蹤 6 個月(§5.2)|
|
||
| Q-FW-5 | KL520 / KL720 / KL630 / KL730 升降版預估時間是否準確 | **開發階段實測** | M9-5(A)/ M9-13(B)三平台實機驗證時校正 |
|
||
| 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 agent、35 分鐘):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` handler(KneronPLUS 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` 細分 stage、Elapsed/ETA 欄位、graceful shutdown 拒絕邏輯 hook 點)| 0.5 人天 | M9-2 | — |
|
||
| M9-4 | 前端 Devices 頁 FW badge(4 色含灰色狀態未知)+ 升級按鈕 + 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.2(R-FW-13)| — |
|
||
| M9-11 | 多版本降版後端(API + bridge.py + driver guards + graceful shutdown 拒絕落地)| 1.5 人天 | M9-9 | — |
|
||
| M9-12 | 降版 UI(Settings 韌體管理面板 + 二次確認 modal + 進行中 UI + Wails 控制台關閉攔截 modal)| 2 人天(Frontend 1 + Design 1)| M9-11 | Design + Frontend 平行 |
|
||
| M9-13 | B 階段三平台實機驗證 + KL520+KL720 wheel 升級 regression + Beta usability test(UR-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` | B(M9-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)| 技術支援 SOP(DFUT.exe 救磚流程,**不打包進 app**)| 上線前 |
|
||
|
||
---
|
||
|
||
## 12. 與既有 R5 決策的關係
|
||
|
||
| R5 條目 | 本任務關係 |
|
||
|---------|----------|
|
||
| **R5-Q9(砍 flash)** | **翻案**(§2),透過範圍切割避開原始擔憂 |
|
||
| **R5-B4(Kneron 預置模型 redistribution)** | 同性質問題擴展 — 本任務的 firmware bundle 與 R5-B4 同樣是「打包 Kneron 智財」、發佈前須一起跟 Kneron 取得授權(§9 Q-FW-1)|
|
||
| **R5-E(60s 啟動 + perceived performance)** | 無關 — FW 升降版不在啟動 pipeline 內(research 30 §2.3)|
|
||
| **R5-D1(Server 崩潰 OS 通知)** | 不擴展 — FW 升降版失敗屬 device 層、不發 OS 通知(與 device toast 一致,PRD v2.1 §AC-3.7 + R4-8 策略)|
|
||
| **R5-1(產品定位)** | 對齊 — FW 管理 UI 住瀏覽器 Web UI(Devices 頁 + Settings 韌體管理)、不住 Wails 控制台 |
|
||
| **R5-3(砍 tray)** | 無衝突 |
|
||
| **R5-6(ffmpeg 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)、但保留各自具體 scope(firmware vs model 兩個 license 範圍)
|
||
- **O-FW-2**(M9-6 強驗證 + AC-FW-3.5 觸發條件):⏳ M9-10 啟動時評估 a/b/c 三條件、任一不滿足 → Orchestrator 派 PM 微調 PRD(KL630/KL730 維持 FW 偵測 only / 不開升降版)
|
||
|
||
### 14.4 互審 Minor 處理紀錄
|
||
|
||
| # | 來源 | 內容 | 處理 |
|
||
|---|------|------|------|
|
||
| M-A1 | Architect TDD §10 R-FW-5 等級「待釐清」| 統一用 P0/P1/P2/P3 分級 | ✅ Architect 修 TDD(PM 不處理)|
|
||
| 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 修 TDD(PM 等對齊結果)|
|
||
| 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 list」vs PRD「dropdown」 | 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 修 TDD、PM 不直接處理 | ⏳ Architect 端處理中 |
|
||
|
||
---
|
||
|
||
## 變更紀錄
|
||
|
||
| 版本 | 日期 | 作者 | 變更 |
|
||
|------|------|------|------|
|
||
| v2.2-draft | 2026-05-24 | PM Agent | 初稿;翻案 R5-Q9;A + 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 命名統一採 Design(preparing/loading/flashing/verifying)②M9 工時表拆法採 PM(Architect 已同意)③AC-FW-3.5(KL630/KL730 升降版)延後到 B 階段 M9-10、補生效條件 a/b/c、A 階段 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 處理紀錄 |
|