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>
577 lines
36 KiB
Markdown
577 lines
36 KiB
Markdown
# Architect 互審報告 — PM PRD + Design Spec(v2.2 Firmware 管理)
|
||
|
||
> 作者:Architect Agent
|
||
> 日期:2026-05-24
|
||
> 任務性質:三方互審 — Architect 視角審 PM PRD + Design Spec
|
||
> 對照基準:
|
||
> - 我的 TDD:`.autoflow/04-architecture/v2/firmware-management.md`
|
||
> - 我的 ADR:`.autoflow/04-architecture/adr/ADR-001-firmware-management.md`
|
||
> - 7 份 research:`.autoflow/04-architecture/research-kl520-fw-management/`
|
||
|
||
---
|
||
|
||
## TL;DR
|
||
|
||
整體判斷:**PM PRD 與 Design Spec 技術上都可實現、與我的 TDD 高度一致、沒有架構衝突。** 但有幾個對齊問題需要解決,主要落在三處:
|
||
|
||
1. **狀態機名稱不對齊**(Design `preparing/loading/flashing/verifying` vs TDD `connecting/loading_loader/loading_firmware/verifying`)—— **必須我修 TDD**(採 Design 的命名、對使用者語意較自然)
|
||
2. **失敗類型 6 vs 8 不一致**(TDD 列 6 stage + 6 錯誤碼、Design 列 8 種失敗類型)—— Design 多列的 `timeout` + `disconnect` 是橫切性失敗、本來就在我的錯誤碼裡(`FW_UPGRADE_FAILED` / `FW_UPGRADE_BRICK_RISK`)—— 補一張對應表即可
|
||
3. **降版進行中 graceful shutdown 拒絕**(Design §14.4 第 6 點自提懸念)—— 我 TDD 沒設計、**必須補進 TDD §8**
|
||
|
||
其餘對齊度高、issue 多為「補一句說明」級。M9-6 不卡 M9-1~5、A 階段可以照計畫啟動。
|
||
|
||
---
|
||
|
||
## 一、對 PM PRD 的審閱
|
||
|
||
### 1.1 AC-FW-* 技術可行性逐條檢視
|
||
|
||
| AC ID | PM 描述 | 技術可行性 | 對應我 TDD 位置 | Issue |
|
||
|-------|---------|----------|---------------|-------|
|
||
| AC-FW-1.1 | scan 後 FW badge 綠/黃/紅三色 | ✅ 可做 | TDD §3.1 `firmwareIsLegacy` / `firmwareCanUpgrade` / `bundledFirmwareVersion` | 無 |
|
||
| AC-FW-1.2 | progress modal 顯示 6 階段 | ⚠️ 名稱不對齊 | TDD §4.3 列 6 stage | **必須修**:見後文 §1.6 |
|
||
| AC-FW-1.3 | 升級成功後 5 秒自動關閉 modal + rescan | ✅ 可做 | TDD §5.1 完成 → driver `needsReset=true` → 下次 connect 走完整 reset | 無 |
|
||
| AC-FW-1.4 | 失敗顯示明確錯誤類型 + 「複製錯誤訊息」 + 「重新插拔後重試」 | ✅ 可做 | TDD §5.3 列 4 種失敗類型、與 Design §7.1 8 種對應見後文 §2.3 | 無 |
|
||
| AC-FW-1.5 | 升級期間 device 進入 `StatusUpgrading` 鎖住其他操作 | ✅ 可做 | TDD §2.2 新增 status enum + §3.3 `FW_DEVICE_BUSY` 409 | 無 |
|
||
| AC-FW-1.6 | 升級成功後等 5-8 秒讓 USB stable | ⚠️ 數字略有出入 | TDD §5.1 / §7.2 用 `sleep 2s` + `sleep 3s` 兩段(合計 5s) | PM 寫 5-8s、TDD 寫 5s。**PM 區間較保守、TDD 是實測值**。建議 PM 改為「5-8 秒(實測 5s 已穩、保留上界容忍)」對齊 |
|
||
| AC-FW-1.7 | KL520 預估 30s、KL720 預估 180s | ✅ 可做 | TDD §3.3 `FW_UPGRADE_FAILED` timeout > 60s、`FW_UPGRADE_BRICK_RISK` timeout > 180s | 無 |
|
||
| AC-FW-1.8 | 升級失敗屬 device 層、不觸發 watchServer Error | ✅ 可做 | TDD §8.1 明確 watchServer 不被觸發 | 無 |
|
||
| AC-FW-2.1 | 降版入口在 Settings →「韌體管理」 | ✅ 可做、與 Design §2 一致(Settings 第 3 分頁) | TDD §5.2 流程進入點 | 無 |
|
||
| AC-FW-2.2~2.4 | 卡片 + dropdown + 紅色按鈕 | ✅ 純前端 | — | 無 |
|
||
| AC-FW-2.5~2.7 | 二次確認 modal + 警告語 + 不可外部關閉 | ✅ 純前端 | — | 無 |
|
||
| AC-FW-2.6 | 強制輸入「DOWNGRADE」字串 | ✅ 可做 | TDD §3.1 / §3.3 `FW_NO_CONFIRM_TOKEN` 400 | 無 |
|
||
| AC-FW-2.8 | 進行中不顯示取消按鈕 + persistent banner | ✅ 純前端 | — | 無 |
|
||
| AC-FW-2.9 | API 強制 `confirmToken: "DOWNGRADE"` | ✅ 可做 | TDD §3.1 / §3.3 明確規格 | 無 |
|
||
| AC-FW-2.10 | Driver 4 項 safety guards | ✅ 可做 | TDD §2.1 `firmware/guards.go` | 無 |
|
||
| AC-FW-3.1~3.4 | KL630/KL730 偵測 + 升降版 + ~60s | ✅ 可做(M9-7~M9-13 落地)| TDD §6.2 chip 判斷擴展 + §9 M9-7~M9-10 | 無 |
|
||
| AC-FW-3.5 | 若 SDK 不支援、降級為 FW 偵測 only | ⚠️ **PM 與 TDD 對齊但缺一條技術判定 trigger** | M9-6 結論後決定 | **詳見 §1.3** |
|
||
|
||
### 1.2 成功指標(PRD §7)的 measurement source 對應
|
||
|
||
| PM 指標 | 我 TDD 是否埋點 | Issue |
|
||
|---------|--------------|-------|
|
||
| 5 分鐘首次推論達成率 +5pp | ❌ 我 TDD 沒設計埋點 | 不是 FW feature 該埋的、應是既有 `/api/system/metrics` 或前端 analytics 範圍。**建議 PM 在 §7.1 註明「指標 source 待定、跨多個 feature 統計」、不要當 FW feature 的 AC** |
|
||
| FW 升級成功率 ≥ 95% | ⚠️ 無自動上報 | TDD §5.1 流程結束會有 `{status:"upgraded", duration_ms}` log、但不會自動上傳。**現階段靠技術支援統計 log、不是自動指標**。建議 PM 在 §7.2 註明「靠 log 統計、非自動上報、待 telemetry feature」 |
|
||
| 升降版平均時長 | ⚠️ 同上 | 同上 |
|
||
| 一般使用者誤觸降版發生率 ≤ 1% | ❌ 完全無法自動量測 | 純客服回報統計、非自動。PM §7.2 已標「客服回報」、OK |
|
||
| Brick 事件 ≤ 0.1% | ❌ 完全無法自動量測 | 純客服回報、PM §7.2 已標、OK |
|
||
|
||
**結論**:PM §7 列的指標**沒有違反技術可行性、但很多依賴客服回報 / 手動統計**。建議 PM 在 §7 開頭加一句「v2.2 階段大部分指標靠客服回報 + log 統計、非自動上報;自動 telemetry 是未來 feature」、避免後續 Reviewer 誤判「指標沒實作」。
|
||
|
||
### 1.3 AC-FW-3.5 生效條件需要明確
|
||
|
||
PM 寫「若 KneronPLUS Python wheel 版本不支援 KL630/KL730 的 update API、降級為 FW 偵測 only」、但**沒寫**「不支援」的判定條件是什麼。我 TDD §6.3 / §7.3 描述了 M9-6 SDK 驗證的範圍、但沒明文說「如果 M9-6 跑出什麼結果 → 觸發 AC-FW-3.5」。
|
||
|
||
**建議補充**(PM 或我都可以補):
|
||
|
||
```
|
||
AC-FW-3.5 生效條件(M9-6 結論其一):
|
||
- 條件 a:KneronPLUS Python wheel 沒有 `kp.core.update_kdp_firmware_from_files` 對 product_id 0x0630/0x0730 的 dispatch
|
||
- 條件 b:SDK 對 .tar firmware 既不支援直接餵、也無法 build-time 解壓出可用 .bin(策略 Z 與 Y 都失敗)
|
||
- 條件 c:升級驗證階段 firmware 字串無法穩定回讀
|
||
```
|
||
|
||
任一條件成立 → AC-FW-3.5 觸發 → B 階段對 KL630/KL730 範圍縮限為「scan + connect + inference + FW 偵測」、移除 upgrade/downgrade UI。
|
||
|
||
### 1.4 工時對齊(M9 表)
|
||
|
||
| 我 TDD §9 | PM §10 | 對齊度 |
|
||
|-----------|--------|-------|
|
||
| M9-0 0.5 文件先行 | 沒列 | PM 沒把文件先行算工時、可接受(屬 Orchestrator 範圍)|
|
||
| M9-1 1.0 bridge.py upgrade | M9-1 1.0 | ✅ |
|
||
| M9-2 1.0 driver + service | M9-2 1.0 | ✅ |
|
||
| M9-3 0.5 API + WS | M9-3 0.5 | ✅ |
|
||
| M9-4 1.5 Frontend | M9-4 1.5 | ✅ |
|
||
| M9-5 1.0 三平台驗證 | M9-5 1.0 | ✅ |
|
||
| M9-6 1.0 SDK 驗證 | M9-6 1.0 | ✅(與 A 平行)|
|
||
| M9-7 0.5 chip 判斷 | M9-7 1.5 | ⚠️ **PM 寫 1.5、我寫 0.5**。0.5 是只改 detector + bridge dispatch;1.5 是含 detector + chip-aware connect 全套(含 KL630/KL730 firmware 載入分支)。**PM 比較保守、可採 PM 數字**(多估留 buffer) |
|
||
| M9-8 1.5 .tar handling | M9-8 1.0 | ⚠️ PM 偏緊、我偏鬆。建議採我 1.5(含策略 Y 解壓 fallback 風險)|
|
||
| M9-9 2.0 KL630/KL730 connect+inference | M9-9 1.0 / M9-10 1.5 | ⚠️ PM 拆成兩個 milestone(多版本目錄重整 + KL630/KL730 升降版)= 2.5。我合併成 M9-9 2.0(純 connect+inference)+ M9-10 1.0(升版擴展)= 3.0。**兩邊算法不同、需要對齊**。詳見 §1.5 |
|
||
| M9-11 1.5 多版本降版 | M9-11 1.5 | ✅ |
|
||
| M9-12 2.0 降版 UI | M9-12 2.0 | ✅ |
|
||
| M9-13 1.0 B 階段驗證 | M9-13 1.0 | ✅ |
|
||
| **A 合計** | 5.0 | 5.0 ✅ |
|
||
| **B 合計** | 10.5 | 10.5 ✅ |
|
||
| **總計** | **15.5** | **15.5 ✅** |
|
||
|
||
**結論**:A/B/總工時對齊、但中間 M9-7~M9-10 拆法不同。**建議 PM 與我用同一張 M9 表**(採 PM 拆法、語意較清楚)、我下輪修 TDD §9 對齊。
|
||
|
||
### 1.5 M9-7~M9-10 拆法差異
|
||
|
||
| Milestone | PM 拆法 | TDD 拆法 | 建議統一 |
|
||
|-----------|--------|---------|---------|
|
||
| M9-7 | Driver 擴 chip + chip-aware connect 分流(1.5 人天)| B0 認 chip(detector + bridge.py + driver)0.5 人天 | **採 PM 的 1.5**(含 chip-aware connect、語意清楚)|
|
||
| M9-8 | .tar handling(1.0)| B1.1 .tar handling(1.5)| **採 TDD 的 1.5**(M9-6 結論若需策略 Y、解壓 build script 工程更大)|
|
||
| M9-9 | 多版本目錄重整(1.0)| B1.2 KL630/KL730 connect + inference(2.0)| **不同 milestone**、PM 與 TDD 對齊不到——詳見後文 |
|
||
| M9-10 | KL630/KL730 升降版(1.5)| B1.3 FW 升版擴 KL630/KL730(1.0)| 同上 |
|
||
|
||
**根因**:PM 把「多版本目錄重整」獨立成 M9-9、TDD 把它合進 M9-11;PM 把「KL630/KL730 inference」併進 M9-7、TDD 拆出 M9-9。**兩邊都對、只是拆法不同**。
|
||
|
||
**建議統一**(採 PM 拆法、語意對外部審閱者更清楚):
|
||
- M9-7:B0 認 chip(driver + bridge.py + detector)1.5 人天
|
||
- M9-8:B1.1 .tar firmware handling 1.5 人天(採 TDD 數字)
|
||
- M9-9:多版本目錄重整 + `_resolve_firmware_paths_versioned()` 1.0 人天
|
||
- M9-10:KL630/KL730 升降版 driver method 1.5 人天
|
||
- M9-11:多版本降版後端 1.5 人天
|
||
- 總和 7.0、+ M9-12 2.0 + M9-13 1.0 = B 階段 10.0、與 PM 10.5 差 0.5(M9-9 KL630/KL730 inference 需要併進去?)
|
||
|
||
**結論**:M9 表需要 PM 與 Architect 對一下、最終一張表。我下輪修 TDD 時對齊 PM 的 §10。
|
||
|
||
### 1.6 R-FW 風險清單對齊
|
||
|
||
| 我 TDD §10 | PM §8 | 對齊度 |
|
||
|------------|-------|-------|
|
||
| R-FW-1 升級中拔除(KL720 寫 flash brick)| R-FW-1 KL520 reset bug 再現 | ⚠️ **語意不同**!PM 的 R-FW-1 是「升級後 device re-enumerate 不穩定」、TDD 的 R-FW-1 是「升級中拔 USB brick」 |
|
||
| R-FW-2 升級後 USB race | R-FW-2 KneronPLUS Python wheel update API 支援度 | ⚠️ 同上、不對齊 |
|
||
| R-FW-3 KL520 已是 KDP2 誤觸發 | R-FW-3 bridge.py `update_kdp_firmware_from_files` macOS x86_64 未驗證 | ⚠️ 同上 |
|
||
| R-FW-4 跨晶片誤匹配 | R-FW-4 timeout 設定不合理 | ⚠️ 同上 |
|
||
| R-FW-5 Kneron 授權 | R-FW-5 打包 Kneron 官方 firmware 是否合法 | ✅ 同概念、PM 標 P0 release gate(與我 ADR §Consequences 對齊)|
|
||
| R-FW-6 HTTP timeout | R-FW-6 既有 `flash/` 模組命名混淆 | ⚠️ 同上 |
|
||
| R-FW-7 Windows admin(WinUSB)| R-FW-7 升級失敗 device unknown state | ⚠️ 同上 |
|
||
| R-FW-8 SDK 對 KL630/KL730 API | R-FW-8 同 | ✅ |
|
||
| R-FW-9 .tar 安裝包衝擊 | R-FW-9 同 | ✅ |
|
||
| R-FW-10 KL630/KL730 沒 Loader mode | R-FW-10 同 | ✅ |
|
||
| R-FW-11 一般使用者誤觸降版 | R-FW-11 同 | ✅ |
|
||
| R-FW-12 多版本管理 UX 複雜度 | R-FW-12 同 | ✅ |
|
||
| R-TAR-1~4(我 TDD 自己加的 4 條)| — | ❌ **PM 沒列**、應補進 PRD §8 |
|
||
|
||
**結論**:
|
||
|
||
1. **R-FW-1~7 的編號 PM 與 TDD 完全不對齊**——可能是 PM 引用了 research 30 的早期編號、我 TDD 內部重新編了。**這是重大問題、必須對齊**。
|
||
2. **建議統一**:採 PM 的 R-FW-1~7 編號(因為 PRD 已是「對外的」風險清單、跨多個下游 agent 引用)、我下輪修 TDD §10 重新對應。
|
||
3. **R-TAR-1~4 PM 沒列**:M9-8 .tar handling 的 4 條技術風險(策略 Z 退回 Y / build script 漏跑 / notarization / 跨平台 tarfile)—— **PM 應補進 PRD §8** 或同意「這 4 條留 TDD §10 即可、不進 PRD」。建議後者:PRD 是給 PM 視角、TAR 風險偏技術細節。
|
||
|
||
### 1.7 Kneron 授權 P0 懸念對齊
|
||
|
||
PM PRD §8.1 R-FW-5 標 **P0 release gate**、§9 Q-FW-1 寫「使用者明示先不管、發佈前再評估」。
|
||
我 ADR-001 §Consequences 寫「法律 / 簽章授權待釐清、與 R5-B4 同性質、發佈前統一處理、不阻塞開發但 PRD P0 懸念」。
|
||
我 ADR-001 §Compliance 標 `[ ] 與 Kneron 取得 firmware redistribution 授權(發佈前必須完成、不阻塞開發)`。
|
||
|
||
**對齊度**:✅ 完全一致。R5-B4 合併處理也與我 ADR §Related 對齊。
|
||
|
||
### 1.8 scope 邊界對齊
|
||
|
||
| 範圍 | PM PRD §2.4 / §3 | 我 TDD §1.2 | 對齊度 |
|
||
|------|-----------------|-----------|-------|
|
||
| 升級到 Kneron 官方 KDP2 標準版本 | ✅ 做 | ✅ 做 | ✅ |
|
||
| 使用者燒任意 model 到 device flash | ❌ 不做(Q9 維持)| ❌ 不做 | ✅ |
|
||
| 使用者選任意 binary 寫 flash | ❌ 不做 | ❌ 不做 | ✅ |
|
||
| 偵測 dongle 當前 FW 版本 | ✅ 做 | ✅ 做 | ✅ |
|
||
| 切換到內建其他 bundle 版本(含降版)| ✅ 做 | ✅ 做 | ✅ |
|
||
| 線上 OTA 更新通道 | ❌ 不做 | ❌ 不做 | ✅ |
|
||
| KL530 / KL830 支援 | 未提及 | ❌ 不做(本期)| ⚠️ **PM 沒列「不做 KL530/KL830」**、建議 PM §3 補一條「**本期不做 KL530 / KL830**(warrenchen 雲端版雖列出、本期排除)」 |
|
||
| DFUT.exe 救磚工具打包 | 未提及 | ❌ 不做 | ⚠️ 同上、PM 應補 |
|
||
|
||
**結論**:scope 大方向一致、但 PM 漏列兩個「不做」(KL530/KL830 + DFUT.exe)。**建議 PM 補進 §3 範圍切割表**。
|
||
|
||
### 1.9 B2 一般使用者降版 — driver/bridge guard 對齊
|
||
|
||
PM AC-FW-2.10 列了 4 項 driver 層 safety guards:
|
||
1. 拒絕跨晶片誤匹配
|
||
2. 拒絕升版偽裝
|
||
3. 拒絕 no-op
|
||
4. 拒絕 status busy
|
||
|
||
我 TDD §2.1 / §3.3 對應如下:
|
||
1. `firmware/guards.go` 拒絕跨晶片 ✅
|
||
2. `firmware/guards.go` 拒絕升版偽裝(`FW_INVALID_DIRECTION` 400)✅
|
||
3. `firmware/guards.go` 拒絕 no-op(同上錯誤碼)✅
|
||
4. `FW_DEVICE_BUSY` 409 ✅
|
||
|
||
**對齊度**:✅ 完全一致、bridge.py `_validate_downgrade_request` 也對應上。
|
||
|
||
---
|
||
|
||
## 二、對 Design Spec 的審閱
|
||
|
||
### 2.1 §11.2 token 對比比率:誰負責新增 design tokens
|
||
|
||
Design §11.2 列了 6 個新 component-level tokens(`color.fw-badge.*`)+ 推導表(Light/Dark 各 6 個值)+ 對比比率(4.7:1 / 5.2:1 / 4.8:1)。
|
||
|
||
**問題**:這些 token 需要寫進 `frontend/src/app/globals.css` 的 `:root` 與 `[data-theme='dark']` block、不是寫進設計文件就會自動生效。
|
||
|
||
**架構層判斷**:
|
||
- Design 文件已明確規格、Frontend 實作時對著抄即可
|
||
- 不需要新增到 `spec/07-design-tokens.md`(既有檔不動、避免架構文件膨脹)
|
||
- **責任歸 Frontend Agent**:M9-4(A 階段、Devices 頁 FW badge)實作時順手加 6 個 CSS variable
|
||
|
||
**Dark 模式 `legacy.fg` 用黑底紅對比的驗證**:Design 推算 4.8:1、實作時 Frontend 用 contrast checker 驗證(如 https://webaim.org/resources/contrastchecker/)。我**不需要 verify 推算數字**、信任 Design 的 oklch 推算。
|
||
|
||
**結論**:Design §11.2 設計合理、無架構層 issue。**Frontend Agent 在 M9-4 落地時負責 CSS variable 寫入 + 驗證**。
|
||
|
||
### 2.2 §6.1 「DOWNGRADE」嚴格比對 — 與 TDD §3.1/§3.3 對齊
|
||
|
||
Design §6.1 規格:
|
||
- input `type="text" autocomplete="off" spellcheck="false"`
|
||
- 比對方式:`event.target.value === 'DOWNGRADE'`(嚴格相等、case-sensitive、不接受小寫/全形/半形/空白)
|
||
- 「確認切換」按鈕 disabled 條件:input 值不等於字面 `DOWNGRADE`
|
||
|
||
我 TDD §3.1 / §3.3:
|
||
- API request body `{version:"v2.1.0", confirmToken:"DOWNGRADE"}`
|
||
- API 強制 `confirmToken === "DOWNGRADE"`(字面字串)
|
||
- 沒帶 / 帶錯 → 400 + `FW_NO_CONFIRM_TOKEN`
|
||
|
||
**對齊度**:✅ 前後端規格完全一致。
|
||
|
||
**Design §14.4 第 4 點懸念(中文 i18n 化)**:Design 建議「短期維持英文字串、跨語言一致」。
|
||
**我的判斷**:✅ 同意。後端 `confirmToken` 是 API contract、不應 i18n 化(會引入 server 端多語對照表、增加攻擊面)。**保留英文字面 `"DOWNGRADE"`、UI 層用 i18n key 顯示提示文字(「請輸入 DOWNGRADE 確認」中文 + 「Type DOWNGRADE to confirm」英文)但 input 比對的字串一致**。
|
||
|
||
### 2.3 §7.1 8 種失敗 stage vs TDD §3.3 6 種錯誤碼 + §5.3 4 種失敗類型對應
|
||
|
||
**Design §7.1 列的 8 種**(後端錯誤 stage → 友善訊息):
|
||
1. `scan` 找不到裝置
|
||
2. `connect` 失敗
|
||
3. `loader` 寫入失敗
|
||
4. `upgrade` 寫入失敗
|
||
5. `verify` 失敗
|
||
6. `Timeout (>60s)`
|
||
7. `Disconnect during op`
|
||
8. (無第 8 項、Design 表格只有 7 列、但 §14.3 表寫「8 種失敗類型對應」、可能是 Design 自己估算誤差)
|
||
|
||
**我 TDD §3.3 列的 6 個錯誤碼**(HTTP 層):
|
||
1. `FW_DEVICE_BUSY` 409
|
||
2. `FW_VERSION_NOT_FOUND` 404
|
||
3. `FW_INVALID_DIRECTION` 400
|
||
4. `FW_NO_CONFIRM_TOKEN` 400
|
||
5. `FW_UPGRADE_FAILED` 500
|
||
6. `FW_UPGRADE_BRICK_RISK` 500
|
||
|
||
**我 TDD §5.3 列的 4 種失敗類型**(流程失敗、不是 HTTP 錯誤碼):
|
||
1. device disconnect during upgrade
|
||
2. firmware load 失敗(pre-flash)
|
||
3. firmware load 失敗(中段、timeout > 180s)
|
||
4. 升級成功但 verify 失敗
|
||
|
||
**對應表**(補進 TDD 與 Design 都需要):
|
||
|
||
| Design §7.1 後端 stage | 我 TDD §3.3 錯誤碼 | 我 TDD §5.3 失敗類型 | 對齊 |
|
||
|----------------------|------------------|------------------|------|
|
||
| `scan` 找不到裝置 | `FW_UPGRADE_FAILED` | (1) disconnect | ✅ |
|
||
| `connect` 失敗 | `FW_UPGRADE_FAILED` | (1) disconnect | ✅ |
|
||
| `loader` 寫入失敗 | `FW_UPGRADE_FAILED` | (2) pre-flash | ✅ |
|
||
| `upgrade` 寫入失敗 | `FW_UPGRADE_FAILED` 或 `FW_UPGRADE_BRICK_RISK` | (3) 中段 / (2) pre-flash | ✅ |
|
||
| `verify` 失敗 | `FW_UPGRADE_FAILED` | (4) verify | ✅ |
|
||
| Timeout (>60s) | `FW_UPGRADE_FAILED` 或 `FW_UPGRADE_BRICK_RISK` | (3) 中段 | ✅ |
|
||
| Disconnect during op | `FW_UPGRADE_BRICK_RISK` | (1) disconnect | ✅ |
|
||
|
||
**結論**:Design 8 種(含 1 種空項)= TDD 6 錯誤碼 + 4 失敗類型的不同切面。**沒有矛盾、只是 granularity 不同**:
|
||
- Design 是「使用者面友善訊息」的分類(給 i18n 用)
|
||
- TDD §3.3 是「HTTP API 錯誤碼」(給 frontend 處理)
|
||
- TDD §5.3 是「服務內部失敗分類」(給 bridge.py 處理)
|
||
|
||
**Issue**:**我 TDD 必須補一張「stage → 錯誤碼 → 失敗類型」對應表**、讓 Frontend / Testing 不會疑惑「Design 列的 8 種對應後端哪個 code」。下輪修 TDD §3.3 後追加 §3.4「stage 對應 friendly message + 錯誤碼」。
|
||
|
||
### 2.4 §8 狀態機名稱 vs TDD §4.3 stage 列舉 — **必須對齊**
|
||
|
||
| Design §8 狀態 | 我 TDD §4.3 stage | 對齊度 |
|
||
|--------------|-----------------|-------|
|
||
| `idle` | — | OK(Design 用、TDD 是 device status) |
|
||
| `confirming` | — | OK(純前端狀態) |
|
||
| `preparing` | `connecting` | ❌ **不對齊**(preparing vs connecting)|
|
||
| `loading` | `loading_loader` | ❌ **不對齊** |
|
||
| `flashing` | `loading_firmware` | ❌ **不對齊** |
|
||
| `verifying` | `verifying` | ✅ |
|
||
| `success_toast` | `done` | ⚠️ 不同切面(toast vs stage 完成)|
|
||
| `error_modal` | `error` | ⚠️ 同上 |
|
||
|
||
**根因**:Design 命名是 UI 視角(preparing 比 connecting 對使用者更友善)、TDD 命名是技術視角(connecting 對應實際的 USB connect 動作)。
|
||
|
||
**判斷**:**Design 的命名對使用者較自然、TDD 應該採 Design 的命名作為 WebSocket event 的 `stage` 值**。理由:
|
||
- progress event 的 `stage` 值最終會被 Frontend 用 i18n key lookup(如 `settings.firmware.progress.stage.preparing`)顯示給使用者
|
||
- 如果 TDD 用 `connecting` 但 Design 的 i18n key 是 `preparing`、Frontend 需要做 mapping、增加複雜度
|
||
- 一致命名讓 Backend / Frontend / Design / Testing 都用同一組詞
|
||
|
||
**動作**:**我下輪必須修 TDD §4.3**、stage 列舉改為:
|
||
- `connecting` → `preparing`(5%)
|
||
- `loading_loader` → `loading`(20%、僅 KDP1→KDP2 路徑)
|
||
- `loading_firmware` → `flashing`(50%)
|
||
- `verifying` → `verifying`(90%、不變)
|
||
- `done` → `done`(100%、不變)
|
||
- `error` → `error`(-1、不變)
|
||
|
||
同時要修 TDD §5.1 流程圖中的 stage 名稱、§6.1 bridge.py handler 回傳的 `stage` 欄位 enum 值。Design §9 i18n keys(`settings.firmware.progress.stage.scan/connect/loader/upgrade/verify`)也需要 Design 對應修為 `preparing/loading/flashing/verifying`——**或者 Design 維持原 key 名、我內部用 Design 的命名**——這需要 Design + Architect 對一下。
|
||
|
||
**建議統一**(給 Orchestrator):
|
||
- **Option A**:TDD 採 Design 的 `preparing/loading/flashing/verifying`、Design 的 i18n key 也改成 `progress.stage.preparing` 等
|
||
- **Option B**:兩邊維持各自命名、TDD 在 §4.3 加一張對應表「TDD stage → Design i18n key」
|
||
|
||
我**建議 Option A**(更乾淨、減少 mapping 心智負擔)。Design 互審我提一下這點、看 Design 是否同意改 i18n key。
|
||
|
||
### 2.5 §14.4 第 6 點:降版進行中 graceful shutdown 拒絕 — **TDD 必須補設計**
|
||
|
||
Design §14.4 第 6 點自提懸念:
|
||
> 「降版進行中關閉 Wails 控制台視窗會發生什麼:依 R5-2 控制台關閉 = 結束 server。降版進行中關控制台 = 中斷降版 = 可能 brick。Frontend / Backend 是否需要在控制台側也偵測『降版進行中』並擋下關閉動作?建議 Architect 補充。」
|
||
|
||
**我 TDD 目前沒設計這個**。檢視 TDD §8:
|
||
- §8.1 watchServer Error state 不被觸發 ✅
|
||
- §8.2 KL520 reset bug 對齊 ✅
|
||
- §8.5 既有 `restartBridge()` 不重用 ✅
|
||
- ❌ **沒提「降版中 graceful shutdown」這條**
|
||
|
||
**Design 提的風險是真實的**:
|
||
- R5-2 規定「關閉 Wails 視窗 = 結束 server」
|
||
- 結束 server = SIGTERM Python sidecar → bridge.py handler 被中斷
|
||
- 如果 `handle_firmware_downgrade` 正在 `update_kdp_firmware_from_files` 中段、SIGTERM 中斷 = **device flash 寫到一半就停 = brick 風險**
|
||
|
||
**設計方向(補進 TDD §8.6)**:
|
||
|
||
```
|
||
### 8.6 降版進行中 graceful shutdown 拒絕
|
||
|
||
當 server 收到 SIGTERM(使用者關閉 Wails 視窗、或 systemd / Wails close handler 觸發)時:
|
||
|
||
1. server 進 `shutting_down` state、停止 accept 新 HTTP 連線
|
||
2. **檢查 `firmware.Service` 是否有 active task**(`StatusUpgrading` / `StatusDowngrading` device)
|
||
3. 如果有 active task:
|
||
a. server **拒絕 graceful shutdown**、回 Wails close handler 一個 `firmwareInProgress: true` 訊號
|
||
b. Wails 控制台收到後**不關閉視窗**、顯示 modal:「韌體切換進行中(device X)、為避免裝置損毀、無法關閉應用程式。請等待約 {遠端推算 ETA}」
|
||
c. modal 不可關閉、不可 dismiss、只能等 firmware task 完成
|
||
d. firmware task 完成後、Wails close handler 重試 graceful shutdown
|
||
4. 如果沒 active task:正常 graceful shutdown(既有 7+1s pattern)
|
||
|
||
實作 hook 點:
|
||
- `server/internal/firmware/service.go`:新增 `HasActiveTask() bool` method
|
||
- Wails close handler(`app.go` 或同等):close 前先 query server `/api/firmware/status`、如果有 active task 顯示 modal 並阻擋 close
|
||
- bridge.py:firmware handler 內加 signal handler 拒絕 SIGTERM(如果有 active task)
|
||
|
||
風險:
|
||
- 使用者強制殺 process(`kill -9` / 強制關機)仍可能 brick、無法完全防範
|
||
- modal 阻擋使用者關 app 可能造成體驗困擾、但 brick 風險高於體驗困擾
|
||
```
|
||
|
||
**結論**:**我下輪必須補 TDD §8.6 + 在 §9 工時表反映**(M9-11 多版本降版後端 + 0.5 人天「graceful shutdown 拒絕」或併入 M9-11)。Design 也應在 control-panel.md 補對應 modal 規格。
|
||
|
||
### 2.6 progress event schema 技術可行性
|
||
|
||
Design §6.3 進行中 UI 需要的欄位:
|
||
- `stage`(階段名稱)
|
||
- `percentage`(進度百分比)
|
||
- `elapsed`(已耗時)
|
||
- `ETA`(預估剩餘時間)
|
||
|
||
我 TDD §4.2 `FirmwareProgress`:
|
||
- `Percent int` ✅
|
||
- `Stage string` ✅
|
||
- `Direction string`
|
||
- `Message string`
|
||
- `Error string`
|
||
|
||
**缺**:`elapsed` 和 `ETA`。
|
||
|
||
**技術可行性**:
|
||
- `elapsed`:✅ 簡單、service goroutine 記錄 task 啟動 timestamp、每次 push event 算 `time.Since(startTime)`
|
||
- `ETA`:⚠️ **複雜**。KneronPLUS C API 沒提供進度回傳(`update_kdp_firmware_from_files` 是 blocking call)、percent 是 bridge.py 自己估算(依 stage hardcode)。如果 stage 內部進度不可知、ETA 只能根據 stage 對應的「預估時長」算(如 `flashing` 階段預計 30s 內完成)、不準確。
|
||
|
||
**結論**:
|
||
- `elapsed` 可以加進 TDD §4.2 ✅
|
||
- `ETA` 也可以加、但**值是估算非精確**、Design 應該在 UI 明示「預估剩餘 ~X 秒」(Design §9.6 已有 `settings.firmware.progress.estimatedRemaining` key、寫「~{seconds}s remaining」、OK)
|
||
|
||
**動作**:**我下輪修 TDD §4.2、加 `Elapsed int64` + `ETA int64` 欄位**。
|
||
|
||
### 2.7 52 個 i18n keys 與 TDD stage 列舉 / 錯誤碼一致性
|
||
|
||
| Design §9 i18n key 類別 | 對應我 TDD | 一致性 |
|
||
|---------------------|-----------|-------|
|
||
| §9.1 頁面結構(7 個)| 純前端、與 TDD 無關 | ✅ |
|
||
| §9.2 裝置卡片(11 個)| 與 TDD §3.1 `DeviceInfo` 衍生欄位對齊 | ✅ |
|
||
| §9.3 版本切換 accordion(11 個)| 純前端、TDD §5.2 流程進入點 | ✅ |
|
||
| §9.4 升級確認 modal(6 個)| 純前端 | ✅ |
|
||
| §9.5 降版二次確認 modal(13 個)| 與 TDD §3.1/§3.3 `confirmToken` 對齊 | ✅ |
|
||
| §9.6 進度 modal(10 個)| ⚠️ **stage 名稱不對齊**(見 §2.4)| **修 §2.4 stage 命名同時對齊**|
|
||
| §9.7 成功 toast(5 個)| 純前端 | ✅ |
|
||
| §9.8 失敗訊息(13 個)| 與 TDD §5.3 失敗類型對應、但對應表缺(見 §2.3)| **TDD 補對應表後一致** |
|
||
| §9.9 Devices 頁 FW badge tooltip(4 個)| 與 TDD §3.1 `firmwareIsLegacy` 對齊 | ✅ |
|
||
|
||
**結論**:52 keys 大部分與 TDD 一致。**只有 §9.6 進度 stage 命名需要在 §2.4 對齊後一併修**。
|
||
|
||
### 2.8 分頁順序「韌體」在硬體與模型之間
|
||
|
||
Design §2 把 Settings 從 4 變 5 分頁、新分頁「韌體」插在第 3 位(一般 / 硬體 / **韌體** / 模型 / 進階)。
|
||
|
||
**架構層影響評估**:
|
||
- **IPC 路由 / API 路徑**:✅ 無影響。我 TDD §3.1 API 路徑用 `/api/devices/:id/firmware/*`、與 Settings UI 分頁順序無關
|
||
- **i18n key namespace**:✅ 無影響。Design 用 `settings.firmware.*`、與分頁順序無關
|
||
- **既有 `settings-update.md` 的 4 分頁結構**:⚠️ 需要更新——Design §14.1 提到「settings-update.md 應在下次補丁加註『分頁順序見 firmware-management.md §2』」、但**沒有改 settings-update.md 本身**。建議 Design 在 v2.2 同步小修 settings-update.md(一行註解即可)
|
||
|
||
**結論**:架構層**無反對**。分頁順序純 UI 決策、Design 已論證合理(硬體 → 韌體 → 模型 由低階到高階)。
|
||
|
||
### 2.9 失敗復原 UX 的 backend 配合
|
||
|
||
Design §7.1 列的 retry / re-plug / 取得協助按鈕:
|
||
|
||
| Design 按鈕 | Backend 配合 | 是否需新 API |
|
||
|-----------|------------|------------|
|
||
| 「重新插拔後重試」 | ✅ 既有 rescan + 重 POST upgrade | ❌ 不需新 API |
|
||
| 「重試」 | ✅ 既有 POST upgrade(同一 device)| ❌ 不需新 API |
|
||
| 「拔插後重試」 | ✅ 同上 | ❌ 不需新 API |
|
||
| 「拔插後重新掃描」 | ✅ 既有 POST /api/devices/scan | ❌ 不需新 API |
|
||
| 「複製錯誤訊息」 | ⚠️ 需 backend 回傳完整錯誤上下文 | **需新增** |
|
||
| 「取得協助」 | ⚠️ 純前端連結(i18n key)| ❌ 不需新 API |
|
||
|
||
**「複製錯誤訊息」的 backend 對齊**:
|
||
- Design §7.2 失敗 modal 內展開「技術資訊」、顯示 `stage / device / before / raw_error / duration_ms`
|
||
- 我 TDD §4.2 `FirmwareProgress.Error string`、§6.1 bridge.py 失敗回傳 `{error:str, stage:"..."}`
|
||
- **缺**:`before`(升級前的 firmware 字串)、`duration_ms`、`device_id` 在 error event 中
|
||
|
||
**動作**:**我下輪修 TDD §4.2、`FirmwareProgress` 在 error event 中應包含完整失敗 context**:
|
||
|
||
```
|
||
type FirmwareProgress struct {
|
||
Percent int `json:"percent"`
|
||
Stage string `json:"stage"`
|
||
Direction string `json:"direction"`
|
||
Message string `json:"message,omitempty"`
|
||
Error string `json:"error,omitempty"`
|
||
Elapsed int64 `json:"elapsed_ms,omitempty"`
|
||
ETA int64 `json:"eta_ms,omitempty"`
|
||
// 失敗時補
|
||
DeviceID string `json:"device_id,omitempty"`
|
||
BeforeVer string `json:"before_version,omitempty"`
|
||
RawError string `json:"raw_error,omitempty"` // bridge.py 拋的原始 exception text
|
||
ErrorCode string `json:"error_code,omitempty"` // 如 "fw_upgrade_stage_loader_E102"
|
||
}
|
||
```
|
||
|
||
### 2.10 R-FW-11.5 / R-FW-11.6 自提風險 — 是否併入 TDD §10
|
||
|
||
Design §12.2 / §12.3 自提兩個風險:
|
||
- **R-FW-11.5**:使用者輸入「downgrade」小寫繞過 — Frontend 用嚴格 `===` 比對、不用 `.toUpperCase()`
|
||
- **R-FW-11.6**:deep-link 跳轉自動展開 accordion 暗示降版 — 改為只 highlight 卡片邊框、不展開
|
||
|
||
**架構層判斷**:
|
||
- **R-FW-11.5**:這是 **Frontend 實作細節**、不是架構層風險。我 TDD §3.1 已要求 backend `confirmToken === "DOWNGRADE"` 嚴格比對(雙重保險)。**不需要進 TDD §10 風險清單**
|
||
- **R-FW-11.6**:純 UX 設計、與架構無關。**不需要進 TDD §10**
|
||
|
||
**結論**:兩個風險都 Design 內部處理、不併入 TDD §10。**但建議 PM PRD §8 補一條 R-FW-11.5(Frontend 嚴格比對)**、明文要求 Reviewer 在 M9-12 檢查 Frontend 是否用了 `===` 而非 `.toUpperCase()`。
|
||
|
||
---
|
||
|
||
## 三、我自己 TDD 自查
|
||
|
||
審完 PM/Design 後、回頭看我的 TDD、發現以下需要下輪修改:
|
||
|
||
### 3.1 必修項(影響跨 agent 對齊)
|
||
|
||
| # | TDD 章節 | 修什麼 | 來源 |
|
||
|---|--------|-------|------|
|
||
| F1 | §4.3 Stage 列舉 | 改名對齊 Design:`connecting → preparing` / `loading_loader → loading` / `loading_firmware → flashing` | §2.4 |
|
||
| F2 | §3.4(新增) | 加「stage → 錯誤碼 → 失敗類型」對應表(給 Frontend / Testing 用)| §2.3 |
|
||
| F3 | §4.2 `FirmwareProgress` | 補 `Elapsed int64` + `ETA int64` + 失敗時補 `DeviceID / BeforeVer / RawError / ErrorCode` | §2.6 / §2.9 |
|
||
| F4 | §8.6(新增) | 補「降版進行中 graceful shutdown 拒絕」設計(HasActiveTask + Wails close handler 攔截)| §2.5 |
|
||
| F5 | §9 工時表 | 對齊 PM 的 M9-7~M9-10 拆法(採 PM 拆法)| §1.5 |
|
||
| F6 | §10 R-FW 風險編號 | 對齊 PM 的 R-FW-1~7 編號(採 PM 編號) | §1.6 |
|
||
| F7 | §5.1 / §6.1 | stage 名稱對齊 F1(包含 bridge.py handler 回傳的 stage enum 值) | §2.4 連動 |
|
||
|
||
### 3.2 建議修但非必要
|
||
|
||
| # | TDD 章節 | 修什麼 | 來源 |
|
||
|---|--------|-------|------|
|
||
| O1 | §1.2 範圍邊界 | 補一條「不做 KL530 / KL830」(雖然 1.2 寫了「KL530 / KL830 不做」、但 PM PRD §3 沒列、可以兩邊對齊一下)| §1.8 |
|
||
| O2 | §10 R-TAR-1~4 | PM 沒列、保留 TDD §10 即可(PM 同意的話)| §1.6 |
|
||
| O3 | §11.2 整合測試表 | 補「升級期間關 Wails 視窗」測試案例(驗證 §8.6 graceful shutdown 拒絕)| §2.5 連動 |
|
||
|
||
### 3.3 不修項(自查後仍然成立)
|
||
|
||
| # | 之前提的 5 個 PM 互審注意 | 是否仍成立 |
|
||
|---|---------------------|---------|
|
||
| 1 | §1.2 範圍邊界 R5-Q9 翻案 | ✅ 仍成立、PM PRD §2 完全對齊 |
|
||
| 2 | §8.4 R5-B4 授權對齊 | ✅ 仍成立、PM PRD §8.1 R-FW-5 標 P0 |
|
||
| 3 | §9 工時 15.5 對齊 | ✅ 總工時對齊、只是 M9-7~M9-10 拆法不同(F5 修)|
|
||
| 4 | §11.4 回歸測試 | ✅ PM PRD 沒寫測試細節、TDD 自帶 OK |
|
||
| — | — | — |
|
||
|
||
| # | 之前提的 5 個 Design 互審注意 | 是否仍成立 |
|
||
|---|---------------------------|---------|
|
||
| 1 | §5.2 降版「DOWNGRADE」字面輸入 | ✅ Design §6.1 已落地 |
|
||
| 2 | §3.3 錯誤碼 + §5.3 失敗復原文案 | ✅ Design §7.1 / §9.8 已落地、但需 F2 補對應表 |
|
||
| 3 | §4.3 Stage 列舉 i18n keys | ⚠️ **需 F1 修 stage 命名後對齊** |
|
||
| 4 | §10 R-FW-11/12 UI 落地 | ✅ Design §12.1 已落地、多層 safety net 完整 |
|
||
| 5 | §4.4 多版本目錄 A → B2 migration | ✅ Design 沒涉及、TDD §4.5 自帶 OK |
|
||
|
||
---
|
||
|
||
## 四、結論
|
||
|
||
### 4.1 PM PRD:通過 — 需小修
|
||
|
||
| 嚴重度 | Issue | 建議 |
|
||
|-------|------|------|
|
||
| Major | M9 工時表 M9-7~M9-10 拆法與 TDD 不對齊 | 對齊一張表(採 PM 拆法)|
|
||
| Major | R-FW-1~7 編號與 TDD 不對齊 | 對齊(採 PM 編號)|
|
||
| Minor | AC-FW-3.5 生效條件不明 | 補 a/b/c 條件(見 §1.3)|
|
||
| Minor | §3 scope 邊界漏列「不做 KL530/KL830 + DFUT.exe」 | PM 補 1 條 |
|
||
| Minor | §7 成功指標 measurement source 模糊 | PM 在 §7 開頭補一句「靠客服回報 + log、非自動 telemetry」|
|
||
| Minor | AC-FW-1.6 USB stable 等待時間 5-8s vs TDD 5s | PM 改為「5-8 秒(實測 5s 已穩、保留上界容忍)」|
|
||
|
||
### 4.2 Design Spec:通過 — 需小修
|
||
|
||
| 嚴重度 | Issue | 建議 |
|
||
|-------|------|------|
|
||
| Major | §8 狀態機名稱與 TDD §4.3 stage 不對齊 | 共識採 Design 命名(preparing / loading / flashing / verifying)、TDD 修 stage、Design i18n key 也對應修 |
|
||
| Major | §14.4 第 6 點 graceful shutdown 拒絕 | Design 提出問題、TDD 補 §8.6 落地 |
|
||
| Minor | §11.2 token 對比比率 Dark legacy.fg | 信任 Design 推算、Frontend M9-4 實作時 verify |
|
||
| Minor | §7.1 8 種失敗 stage 對應不清晰 | Design + TDD 共同補對應表(給 Frontend / Testing 用)|
|
||
| Minor | progress event 缺 `elapsed` / `ETA` | TDD §4.2 補欄位 |
|
||
| Minor | settings-update.md 沒更新分頁順序 | Design 在 v2.2 同步小修一行 |
|
||
|
||
### 4.3 我自己 TDD:需修 7 項必修 + 3 項建議
|
||
|
||
詳見 §3.1 / §3.2。**我下輪修 TDD**、目標:
|
||
|
||
- F1-F7 全修(必修)
|
||
- O1-O3 視情況修(建議)
|
||
- ADR-001 不需修(仍然 Accepted、決策邏輯沒變)
|
||
|
||
### 4.4 整體判斷
|
||
|
||
- **架構層**:✅ 通過、PM/Design/Architect 三方在 R5-Q9 翻案、A+B 範圍、+7MB 安裝包、CURRENT_VERSION 多版本目錄、二次確認 DOWNGRADE 字串、watchServer 解耦等核心架構決策完全對齊
|
||
- **介面層**:⚠️ 需修 F1(stage 命名)+ F2/F3(progress event schema 補欄位)+ F4(graceful shutdown 拒絕)
|
||
- **工時 / 風險**:⚠️ 需修 F5(M9 表)+ F6(R-FW 編號)
|
||
- **M9-6 SDK 驗證**:不卡 A 階段、M9-1~5 可以照計畫啟動
|
||
|
||
---
|
||
|
||
## 五、給 Orchestrator 的建議
|
||
|
||
### 5.1 互審後的處理順序(建議)
|
||
|
||
```
|
||
1. Orchestrator 收齊三方互審報告(PM 審 Design+Architect、Design 審 PM+Architect、本報告 = Architect 審 PM+Design)
|
||
2. 跨報告比對、識別「共識點」「分歧點」
|
||
3. 對齊以下幾個關鍵點:
|
||
a. M9 工時表(採 PM 拆法、總和 15.5 不變)
|
||
b. R-FW 編號(採 PM 編號)
|
||
c. stage 命名(採 Design 命名:preparing / loading / flashing / verifying)
|
||
d. graceful shutdown 拒絕(補 TDD §8.6 + Design control-panel.md 補 modal)
|
||
4. 確認分歧後、派 Architect 修 TDD(F1-F7 + 視情況 O1-O3)
|
||
5. 派 PM 微修 PRD(§1.3 + §3 scope 補 + §7 measurement 註解 + §10 表 M9-7~M9-10 拆法 + R-FW-1~7 對齊)
|
||
6. 派 Design 微修(§7 失敗對應表 + settings-update.md 一行 + 同意 stage 命名)
|
||
7. 第二輪互審(小規模、只審修改處)
|
||
8. 通過 → 進 M9-1 / M9-6 開發
|
||
```
|
||
|
||
### 5.2 不需要 Orchestrator 額外裁決的事
|
||
|
||
| Item | 為何不需裁決 |
|
||
|------|----------|
|
||
| token 對比比率 | Frontend M9-4 實作時驗證、Design 推算先信任 |
|
||
| R-FW-11.5 / R-FW-11.6 自提風險 | Design 內部處理、不進 TDD §10 |
|
||
| KL530/KL830 不做 | 三方都已隱性同意、PM 補一行即可 |
|
||
| Confirm token 「DOWNGRADE」未來 i18n 化 | 短期維持英文、Architect + Design 已同意(不分語系)|
|
||
|
||
### 5.3 需要 Orchestrator 裁決的事
|
||
|
||
| Item | 選項 |
|
||
|------|-----|
|
||
| stage 命名最終採哪一邊 | A. 採 Design(preparing / loading / flashing / verifying)✅ 建議;B. 採 TDD(connecting / loading_loader / loading_firmware / verifying)|
|
||
| M9 表最終採哪一邊拆法 | A. 採 PM 拆法 ✅ 建議;B. 採 TDD 拆法;C. 折衷 |
|
||
| graceful shutdown 拒絕的 modal | Design 補 control-panel.md / Architect 補 TDD §8.6 / 工時影響(建議併入 M9-11)|
|
||
|
||
---
|
||
|
||
## 變更紀錄
|
||
|
||
| 日期 | 版本 | 變更 | 作者 |
|
||
|------|------|------|------|
|
||
| 2026-05-24 | v1.0 | 初稿、Architect 視角審 PM PRD + Design Spec、識別 F1-F7 必修項 + 6 個 PM Minor + 6 個 Design Minor | Architect Agent |
|