# M9-6 弱驗證結果(不含實機) > 對應 `50-m9-6-sdk-validation.md` 的弱驗證執行 > 執行日期:2026-05-24 > 執行者:Architect Agent > 路徑使用相對路徑(相對於 `/Users/jimchen/visionA/local-tool/`) --- ## 環境 - **執行平台**:macOS / sandboxed Architect Agent context(無 Bash tool、無實機 dongle) - **執行限制**: - 不能解壓 wheel binary(沒 Bash / `unzip` 可用、Read 對 deflate-compressed zip 內容只看到亂碼) - 不能跑 Python REPL 確認 enum 值 - 不能解壓 `.tar` 看內容 - 不能 ssh 到實機 - **可用證據來源**: 1. warrenchen prototype(`/tmp/web_academy_prototype/`)的 Python source code 2. visionA-local 既有 `server/scripts/kneron_bridge.py`(看我們現在用了哪些 kp API) 3. 既有研究檔 §00-§42 4. warrenchen bundled wheel filename pattern:`KneronPLUS-3.1.2-py3-none-any.whl` 5. 既有 visionA-local wheel:`KneronPLUS-2.0.0-py3-none-any.whl`(macOS/Linux)+ `KneronPLUS-3.1.2-py3-none-any.whl`(Windows)—— **wheel 版本三平台不一致**(重要發現) --- ## 結論(TL;DR) 1. **KneronPLUS 3.1.2 確認支援 KL630/KL730 enum**——warrenchen `main.py` L433-447 直接用 `kp.ProductId.KP_DEVICE_KL630/KL730/KL830`、運作中、enum 存在無疑。 2. **`update_kdp_firmware_from_files` API 在 KneronPLUS 3.1.2 存在且 warrenchen 已使用**——`update_kl720_firmware.py` 與 `legacy_plus121_runner.py` 兩個檔案大量使用 `lib.kp_update_kdp_firmware_from_files(dg, scpu, ncpu, auto_reboot)`。這是 KDP1 → KDP2 升版(flash 寫入)的關鍵 API。 3. **`connect_devices_with_magic_pass` 概念存在、實際 API 是 `kp_connect_devices` + `KDP_MAGIC_CONNECTION_PASS=0x1FF55B4F` 狀態碼**——warrenchen 用此 magic value 繞過 KDP1 firmware 檢查、連到 legacy device、再寫 flash。這是 ctypes-level call、Python 層 `kp.core.connect_devices_without_check` 可能是同一 API 的 wrapper(待強驗證確認)。 4. **`load_firmware_from_file` 只接受兩個 .bin 路徑(scpu, ncpu)、不接受 .tar**——warrenchen `FirmwareLoadRequest` schema 強證據:`scpu_path: str` + `ncpu_path: str`、無 `tar_path` 欄位。**策略 Z(直接餵 .tar 給 SDK)不可行**。 5. **沒有 `load_firmware_from_tar` / `update_kdp_firmware_from_tar` API**——warrenchen 完全沒有用、且若存在會出現在 `FirmwareLoadRequest` 或 `legacy_plus121_runner.py`。**策略 Y(build time 解壓 .tar 找 .bin)是唯一可行解**。 6. **warrenchen 對 KL630/KL730 的 firmware 升降版完全沒實作**——只有 KL520 + KL720 兩個 chip-specific endpoint(`/firmware/legacy-upgrade/kl520` + `/firmware/legacy-upgrade/kl720`)、KL630/KL730 沒有對應 endpoint。**這是設計 gap、不是 SDK 限制**。意味我們設計 A 階段的 `handle_firmware_upgrade` for KL630/KL730 時、沒有 reference 實作可抄、要自己根據 KneronPLUS SDK 推。 7. **重大發現:visionA-local wheel 三平台版本不一致**——macOS/Linux 是 `KneronPLUS-2.0.0`、Windows 是 `KneronPLUS-3.1.2`。**2.0.0 是否含 `KP_DEVICE_KL630/KL730` enum 無法靜態確認**——`KP_DEVICE_KL720_LEGACY` 在 3.1.2 確認存在(warrenchen L432)但 2.0.0 不確定。**強驗證必跑**:在 macOS + Linux 上實際 `import kp; print(kp.ProductId.KP_DEVICE_KL630)` 看是否存在。 8. **PRD AC-FW-3.5(KL630/KL730 升降版)的可行性結論**: - **理論上可行**(SDK API 都在、enum 都在、`update_kdp_firmware_from_files` 對所有 chip 通用) - **但弱驗證無法 100% 證明對 KL630/KL730 適用**——`update_kdp_firmware_from_files` 是否分支判斷 chip、KL630/KL730 是否走同一條 flash 寫入路徑、必須實機 confirm - **建議**:A 階段不開 KL630/KL730 升降版(PRD AC-FW-3.5 暫降為 B 階段功能或標 "Tentative")、B 階段 M9-9 / M9-10 啟動時實機強驗 --- ## Unknown 對照表 對應 `50-m9-6-sdk-validation.md` §2 的 10 個驗證項目: | # | 類別 | Unknown | 弱驗證結果 | 仍需強驗證? | 影響 | |---|------|---------|-----------|------------|------| | A-1 | A | 既有 wheel 版本 | **三平台不一致**:macOS/Linux 2.0.0、Windows 3.1.2(從 `visiona-local/wheels/*` glob 結果直接確認) | N(已從檔名確認版本) | TDD §「KneronPLUS wheel 升級」必須記錄三平台不一致、考量是否統一升級到 3.1.2 | | A-2 | A | wheel 內 `KP_DEVICE_KL630/KL730` enum | **3.1.2 確認有**(warrenchen `main.py` L433-447 使用中);**2.0.0 待 Y**——靜態無法確認,需在 macOS/Linux 跑 `python3 -c "import kp; print(kp.ProductId.KP_DEVICE_KL630)"` | Y(對 2.0.0) | 若 2.0.0 沒有 enum → 必須在 macOS/Linux 升級 wheel 到 3.1.2(會引入 KL520/KL720 regression 風險) | | A-3 | A | `load_firmware_from_file` 對 .tar 行為 | **不接受 .tar、只接受兩個 .bin 路徑**(warrenchen `FirmwareLoadRequest` schema = `scpu_path: str` + `ncpu_path: str` 強證據;`legacy_plus121_runner.py` L44-45 `lib.kp_load_firmware_from_file.argtypes = [c_void_p, c_char_p, c_char_p]`、兩個 c_char_p 對應兩個檔案) | N(schema 與 ctypes 簽名已強證據) | **策略 Z 確定不可行、必走策略 Y**(build time 解壓 .tar);TDD §「.tar firmware 處理」改為策略 Y 唯一方案、`_resolve_firmware_paths` 設計需走 `extracted/fw_scpu.bin` 路徑 | | A-4 | A | `load_firmware_from_tar` / `update_*_from_tar` 是否存在 | **不存在**(warrenchen 完全沒用、若存在會出現在 `FirmwareLoadRequest` 或 `legacy_plus121_runner.py`;warrenchen 對 KL630/KL730 .tar 也沒有特別處理 endpoint) | N(負面證據強) | 同 A-3、策略 Z 排除 | | A-5 | A | `update_kdp_firmware_from_files` 對 KL630/KL730 適用性 | **API 在 3.1.2 確認存在、簽名為 `(dg, scpu_path, ncpu_path, auto_reboot_bool)`**(warrenchen `update_kl720_firmware.py` L110-120 與 `legacy_plus121_runner.py` L46-47 都明示);但**對 KL630/KL730 是否走同一條 flash 寫入路徑、無從靜態判斷**——warrenchen 對 KL630/KL730 完全沒用此 API(沒有對應 endpoint) | Y(高度需要) | A 階段 KL630/KL730 升降版(PRD AC-FW-3.5)暫排除;B 階段 M9-10 啟動前實機強驗、決定走 `update_kdp_firmware_from_files` 還是要找新 API | | A-6 | A | wheel 升級對 KL520/KL720 regression 範圍 | **wheel 2.0.0 → 3.1.2 跨主版本、breaking change 風險高**——但無法靜態查 changelog(沒 Kneron 官方文件 access);既有 visionA-local kneron_bridge.py 用的 API(scan_devices、connect_devices、load_firmware_from_file、reset_device、load_model_from_file、generic_image_inference_send/receive、ChannelOrdering、GenericImageInferenceDescriptor、ImageFormat、ResetMode)**這些 API 全部在 warrenchen 3.1.2 程式碼也有使用**(即 3.1.2 仍然支援)→ **可能可升級而不破壞既有 KL520/KL720** | Y(必須三平台跑 E2E) | 升 wheel 風險可控(API 介面相容性看起來高);但必須 M9-13 三平台跑 KL520+KL720 完整 E2E 才能確定 | | B-1 | B | KL630/KL730 USB scan product_id | **仍需實機**——0x0630/0x0730 是「研究階段假設」(從 visionA-local + warrenchen edge-ai 兩端 `_KNOWN_PRODUCTS` map 都這樣寫、但這些 map 是寫程式人猜的、warrenchen LocalAPI 程式碼**不直接用 product_id hex、而是用 `kp.ProductId.KP_DEVICE_KL630` enum 物件**) | Y(必須有實機 dongle) | A/B 階段 driver `_KNOWN_PRODUCTS` map 維持 0x0630/0x0730 假設、但 M9-9 實機驗證時若不符要立刻調整 | | B-2 | B | KL630/KL730 是否每次 connect 都要 load firmware | **仍需實機**——warrenchen 完全沒對 KL630/KL730 寫 connect/firmware load 流程、無 reference;KL520 是「USB Boot 必載」、KL720 是「flash-based 不載」、KL630/KL730 推測「flash-based 不載」(同新世代 SDK packaging 風格)但**僅推測** | Y | M9-9 啟動時實機跑「連續 connect 兩次、看第二次需不需要重 load」 | | B-3 | B | KL630/KL730 firmware 字串可能值 | **仍需實機**——warrenchen 沒任何 KL630/KL730 firmware 字串紀錄;KL520/KL720 我們既有觀察值是 `"KDP"` / `"KDP2"` / `"Loader"` / `""` 等 | Y | M9-9 實機 scan_devices() 直接看 `dev.firmware` 欄位 | | C-1 | C | .tar 檔案內容 | **無法弱驗證**——`.tar` 是 binary、Grep tool 對 binary 跳過、無 Bash 跑 `tar -tvf`;唯一資訊:檔名 `kp_firmware.tar` + `kp_loader.tar`、warrenchen 對 .tar 內容沒留下 inspect 結果 | Y(執行 `tar -tvf` 即可、無需實機) | M9-8 啟動前用 Bash 跑一次 `tar -tvf` 即解;不阻塞 A 階段任何工作 | **統計**: - A 類 6 項 → 4 項弱驗證有答案、2 項需強驗證(A-2 對 2.0.0、A-5 對 KL630/KL730 適用性、A-6 升 wheel regression) - B 類 3 項 → 0 項弱驗證有答案、3 項全需強驗證(必有實機) - C 類 1 項 → 弱驗證可解但需 Bash(Architect Agent 限制、移交 backend agent 5 分鐘可完成) --- ## 重點發現 ### 發現 1:KneronPLUS 3.1.2 enum 列表(從 warrenchen `main.py` L427-447 直接讀) ```python KP_DEVICE_KL520 KP_DEVICE_KL720 # 0x0720 (KDP2 新版) KP_DEVICE_KL720_LEGACY # 0x0200 (KDP1 老版、需走 magic pass) KP_DEVICE_KL630 KP_DEVICE_KL730 KP_DEVICE_KL830 # 多一個未在 visionA-local 研究範圍的 chip ``` **意涵**: - KL720 有兩個 enum value(`KL720` 對應 KDP2 / `KL720_LEGACY` 對應 KDP1)、跟我們既有 visionA-local 認知一致 - **KL630/KL730 各只有一個 enum**——支持「KL630/KL730 沒有 legacy/new 雙版本」的假設(前一輪研究 §5.2 推測) - **KL830 存在於 SDK 但 warrenchen 沒實作**——可能是更新一代的 chip、與本研究範圍無關 ### 發現 2:`update_kdp_firmware_from_files` 完整簽名(從 `legacy_plus121_runner.py` L46-47 + `update_kl720_firmware.py` L110-120) ```python # ctypes 層級簽名 lib.kp_update_kdp_firmware_from_files.argtypes = [ ctypes.c_void_p, # device_group handle ctypes.c_char_p, # scpu_path (or None) ctypes.c_char_p, # ncpu_path (or None) ctypes.c_bool, # auto_reboot ] lib.kp_update_kdp_firmware_from_files.restype = ctypes.c_int # 0 = success # 用法 1:先 flash SCPU(不 reboot) ret = lib.kp_update_kdp_firmware_from_files(dg, scpu_path.encode("utf-8"), None, False) # 手動 reset + reconnect lib.kp_reset_device(dg, 0) # KP_RESET_REBOOT = 0 # 用法 2:再 flash NCPU ret = lib.kp_update_kdp_firmware_from_files(dg, None, ncpu_path.encode("utf-8"), False) # 用法 3:一次 flash 兩個 + auto reboot(legacy_plus121_runner.py L233 走這條) ret = lib.kp_update_kdp_firmware_from_files(dg, loader_path.encode("utf-8"), None, True) ``` **意涵**: - API 支援獨立 flash SCPU 或 NCPU(其中一個 path 傳 None) - `auto_reboot=True` 由 SDK 自己 reset device、caller 不需要再 `reset_device`、但接下來 `disconnect_devices` 可能會回 non-zero(USB re-enumeration、warrenchen `legacy_plus121_runner.py` L273-277 明示這個情況) - **Python wrapper `kp.core.update_kdp_firmware_from_files` 是否存在 / 簽名相同**——warrenchen 全部用 ctypes direct call、**沒用 Python wrapper**。這暗示 Python wrapper 可能不存在、或存在但 warrenchen 故意繞過(保有更多 error code 控制) ### 發現 3:`KDP_MAGIC_CONNECTION_PASS = 0x1FF55B4F`(從 `update_kl720_firmware.py` L31 + `legacy_plus121_runner.py` L12) ```python KDP_MAGIC_CONNECTION_PASS = 0x1FF55B4F # = 536173391 decimal # 連到 KDP1 legacy device 的方式(繞過 firmware version check) port_ids = (ctypes.c_int * 1)(port_id) status = ctypes.c_int(KDP_MAGIC_CONNECTION_PASS) dg = lib.kp_connect_devices(1, port_ids, ctypes.byref(status)) # status.value 之後會被 SDK 改寫成實際的 connect result code ``` **意涵**: - `kp_connect_devices` 的第三個參數(status pointer)有**雙向用途**:caller 傳入 magic value、SDK 寫回 result code - visionA-local 既有 bridge.py 用 `kp.core.connect_devices_without_check` 走 Python wrapper(不需直接操作 magic)——**這兩個 API 可能是同件事的兩種 binding**(Python wrapper 內部就傳 magic value) - B 階段擴 KL630/KL730 時、如果碰到「old firmware 連不上」、需要 magic pass、可以複製 warrenchen 這個 pattern ### 發現 4:`FirmwareLoadRequest` schema 證明 `.tar` 不被 SDK 接受 ```python # main.py L169-171 class FirmwareLoadRequest(BaseModel): scpu_path: str ncpu_path: str ``` **意涵**: - warrenchen 對外暴露的 firmware load API 強制要求兩個 .bin 路徑 - 若 SDK 接受 .tar、warrenchen 早該開 `tar_path: Optional[str]` 欄位 - 這個 schema 是 warrenchen 對 SDK 行為的最終共識——**.tar 不能直接餵、必須先解壓** ### 發現 5:warrenchen 沒有 `/firmware/legacy-upgrade/kl630` 或 `kl730` endpoint ```python # main.py 全部 firmware endpoint: @app.post("/firmware/load") # generic,caller 自己給 path @app.post("/firmware/legacy-plus121/load") # KL720 KDP1 → KDP2 RAM-based @app.post("/firmware/legacy-upgrade/kl520") # KL520 DFUT 路徑 @app.post("/firmware/legacy-upgrade/kl720") # KL720 DFUT 路徑 # ❌ 沒有 legacy-upgrade/kl630 # ❌ 沒有 legacy-upgrade/kl730 ``` **意涵**: - warrenchen 對 KL630/KL730 升降版的設計 gap(**不是 SDK 限制、是 warrenchen 沒做**) - 我們做 A 階段(PRD AC-FW-3.5)時、不能直接抄 warrenchen 模式——要自己設計 KL630/KL730 升降版流程 - 對 PRD 影響:AC-FW-3.5(KL630/KL730 升降版)的**參考實作不存在**、設計工時要拉高(M9-10 原估 1 人天可能不夠) ### 發現 6:visionA-local wheel 三平台版本不一致 ``` visiona-local/wheels/macos/KneronPLUS-2.0.0-py3-none-any.whl visiona-local/wheels/linux/KneronPLUS-2.0.0-py3-none-any.whl visiona-local/wheels/windows/KneronPLUS-3.1.2-py3-none-any.whl ``` **意涵**: - 目前 visionA-local 在三平台跑的 KneronPLUS API 行為**可能不一致**(API 跨主版本可能有 breaking change) - 既有 KL520/KL720 在三平台都能 work 的事實 → 既有 bridge.py 用的 API subset 在 2.0.0 和 3.1.2 都存在 - **但 KL630/KL730 enum 在 2.0.0 是否存在無法靜態確認** - A 階段(PRD AC-FW-3.5)若要在 macOS + Linux 也支援 KL630/KL730 升降版、**必須先升級 macOS/Linux wheel 到 3.1.2**——這會引入 KL520/KL720 regression 風險、必須 M9-13 三平台 E2E 跑過才放心 - **PRD AC-FW-3.5 對三平台一致性的影響**:A 階段若維持「只支援 KL520+KL720」、wheel 三平台不一致可暫不處理;A 階段若要加 KL630/KL730、wheel 升級是強制前提 ### 發現 7:既有 visionA-local bridge.py 對 `load_firmware_from_file` 的使用模式 ```python # server/scripts/kneron_bridge.py L760-762 (KL720 KDP1 → load KDP2 to RAM) kp.core.load_firmware_from_file( _device_group, scpu_path, ncpu_path ) ``` **意涵**: - 我們既有用的是 **RAM-based load**(每次 connect 都重新 load 到 RAM、不寫 flash) - warrenchen 走兩條路: - `kp.core.load_firmware_from_file`(RAM-based、`firmware_legacy_plus121_load` endpoint 走這條) - `lib.kp_update_kdp_firmware_from_files`(flash-based、permanent、`update_kl720_firmware.py` 走這條) - **PRD AC-FW-3.1(KDP1 → KDP2 升版)的兩種實作策略**: - **策略 RAM-based**(既有 visionA-local 做法):每次 connect 重新 load、不寫 flash、永久效果需 USB 不拔 - **策略 Flash-based**(warrenchen `update_kl720_firmware.py` 做法):寫進 flash 永久生效、device reboot 後 product_id 從 0x0200 → 0x0720 - A 階段選哪個策略需要 PM/Architect 在 PRD 中明示——**這是 PRD 缺失**、應該補 --- ## 對 PRD AC-FW-3.5 的影響 `feature-firmware-management.md` AC-FW-3.5(推測為 KL630/KL730 升降版)的弱驗證結論: | 項目 | 弱驗證結論 | 對 AC-FW-3.5 影響 | |------|----------|------------------| | SDK enum 存在 | ✅ 3.1.2 確認有;2.0.0 待驗 | macOS/Linux 必先升 wheel | | `update_kdp_firmware_from_files` API 存在 | ✅ 3.1.2 確認 | API 層可用 | | 對 KL630/KL730 適用 | ⚠️ 無 reference 實作、warrenchen 沒做 | **參考實作為零、設計工時加倍** | | .tar firmware 處理 | ✅ 走策略 Y(build time 解壓)即可 | TDD §41 確定方案 | | 實機驗證 | ❌ 必需 | M9-10 啟動前不能跳過 | **建議**: - AC-FW-3.5 **不適合放 A 階段 MVP**——理由: 1. 無 warrenchen reference 實作(design risk 高) 2. wheel 三平台不一致、A 階段要做 KL630/KL730 升降版必先處理 wheel 升級(額外 1-1.5 人天 + regression 風險) 3. 沒實機根本沒法 verify - AC-FW-3.5 **延後到 B 階段 M9-10**: - 此時 M9-9(KL630/KL730 connect + inference)已實機驗過 - wheel 升級決策已根據 M9-6 強驗證結果決定 - 真正能寫 + 測 + 跑 --- ## 對 TDD §X.X 的影響 需要立即修改的章節(M9-6 弱驗證後就能改、不必等強驗證): | 檔案 | 章節 | 修改內容 | 優先級 | |------|------|---------|--------| | `04-architecture/v2/firmware-management.md` | KneronPLUS wheel 版本 | 註記三平台不一致(macOS/Linux 2.0.0、Windows 3.1.2)+ A 階段是否升級的決策建議 | 高 | | `04-architecture/v2/firmware-management.md` | `_resolve_firmware_paths` 設計 | **明示策略 Y(build time 解壓)為唯一方案**、刪除策略 Z 描述 | 高 | | `04-architecture/v2/firmware-management.md` | KL520 / KL720 升版策略 | 明示「RAM-based vs Flash-based」兩種方案差異、選定其一 | 高 | | `04-architecture/v2/firmware-management.md` | KL630/KL730 升降版 | 標 "B 階段才實作、A 階段不開";附 warrenchen 沒做的事實 | 高 | | `04-architecture/v2/firmware-management.md` | API call list | 補 `kp_connect_devices` + magic_pass 機制(從 warrenchen 確認的 pattern) | 中 | | `04-architecture/research-kl520-fw-management/41-tar-firmware-handling.md` | §4.4 決策樹 | 標策略 Z 已排除、走策略 Y | 高 | | `04-architecture/research-kl520-fw-management/40-b-phase-kl630-kl730-extension.md` | §3.2 表格 | 填入「弱驗證結果」column(A 類 4 項) | 高 | | `04-architecture/research-kl520-fw-management/40-b-phase-kl630-kl730-extension.md` | R-FW-8 | 升級為「中度風險」(KneronPLUS 3.1.2 enum 確認後、剩 2.0.0 升級 + KL630/KL730 適用性風險) | 中 | | `04-architecture/research-kl520-fw-management/50-m9-6-sdk-validation.md` | §8.1 / §8.2 / §8.3 | 填弱驗證結果(連結本檔) | 高 | | `02-prd/features/feature-firmware-management.md` | AC-FW-3.5 | 標 "B 階段才實作、A 階段不開"、附 M9-6 弱驗證理由 | 高 | --- ## 強驗證仍需執行的項目 剩下的、必須等硬體 / Bash 才能驗: | # | 項目 | 何時做 | 預估工時 | 是否阻塞 A 階段 | |---|------|--------|---------|---------------| | A-2(2.0.0 part) | macOS + Linux 跑 `python3 -c "import kp; print(kp.ProductId.KP_DEVICE_KL630)"` | M9-6 強驗證階段(無需實機 dongle、只需 venv) | 30 分鐘 | **是**——影響 wheel 升級決策 | | A-5 | KL630/KL730 dongle + `lib.kp_update_kdp_firmware_from_files` flash 測試 | M9-10 啟動前 | 0.5 天 | 否(A 階段不做 KL630/KL730 升降版) | | A-6 | wheel 2.0.0 → 3.1.2 升級後 KL520+KL720 三平台 E2E | M9-13 | 1 天 | 否(如果 A 階段不升 wheel) | | B-1 | KL630/KL730 USB scan product_id | M9-9 啟動前 | 30 分鐘 | 否 | | B-2 | KL630/KL730 是否每次 connect 重 load firmware | M9-9 | 1 小時 | 否 | | B-3 | KL630/KL730 firmware 字串可能值 | M9-9 | 30 分鐘 | 否 | | C-1 | `.tar` 內容(用 `tar -tvf`、無需實機) | M9-8 啟動前 | 5 分鐘 | 否(策略 Y 已確定) | **A 階段啟動前必跑(阻塞)**:只有 A-2(2.0.0 wheel enum 驗證)一項、30 分鐘可解。 --- ## 給 Orchestrator 的建議 ### 1. 弱驗證結論是否足以開始 A 階段開發? **結論**:**可以**——但要先: - 派 backend agent 在 macOS/Linux 跑 30 分鐘的 A-2 強驗證(即 `python3 -c "import kp; print(kp.ProductId.KP_DEVICE_KL630)"`) - 結果有兩個分支: - **2.0.0 有 KL630/KL730 enum** → 不阻塞 A 階段、可以照原計畫做 KL520+KL720 PRD 範圍 - **2.0.0 沒有 KL630/KL730 enum** → 仍可不阻塞 A 階段(A 階段不做 KL630/KL730);但 PRD AC-FW-3.5 必須明示「需先升 wheel」 - 派 backend agent 跑 C-1(`tar -tvf` inspect)5 分鐘可解 ### 2. 強驗證執行時機建議 - **立刻可做**(無實機):A-2(2.0.0 part)+ C-1 → 30 分鐘 + 5 分鐘 - **M9-9 啟動前**:B-1 + B-2 + B-3(需 KL630/KL730 實機) - **M9-10 啟動前**:A-5(需 KL630/KL730 實機跑 flash 測試) - **M9-13**:A-6(三平台 wheel 升級 regression) ### 3. 哪些 PRD/TDD 內容需要立即修改、哪些可等強驗證 **立即修改(不必等強驗證)**: - TDD `04-architecture/v2/firmware-management.md`: - `_resolve_firmware_paths` 走策略 Y、刪策略 Z - 註記 wheel 三平台不一致 + A 階段升 wheel 與否決策 - KL630/KL730 升降版章節標「B 階段才實作」 - PRD `02-prd/features/feature-firmware-management.md`: - AC-FW-3.5 明示「B 階段才實作、A 階段不開」+ 理由 - 研究檔 `40-b-phase-kl630-kl730-extension.md` + `41-tar-firmware-handling.md`: - §3.2 / §5.2 / §4.4 填弱驗證結果 - 研究檔 `50-m9-6-sdk-validation.md`: - §8.1 連結本檔 **等強驗證才修改**: - wheel 升級最終決策(等 A-2 + A-6 強驗證) - KL630/KL730 connect 流程設計細節(等 B-1 + B-2 + B-3) - KL630/KL730 升降版 API 選擇(等 A-5) ### 4. 派工建議 - **A-2 強驗證**:派 backend agent、目標檔 `.autoflow/04-architecture/research-kl520-fw-management/55-m9-6-weak-validation-result.md` 補「A-2 強驗證結果」段落 - **C-1 強驗證**:同 backend agent 順手做、5 分鐘 - **TDD/PRD 修改**:派 architect agent(我)做 TDD 修改、Orchestrator 自行修 PRD AC-FW-3.5 標註 --- ## 與其他研究檔的關係 | 連結 | 引用內容 | |------|---------| | `50-m9-6-sdk-validation.md` §2 | 本檔 §「Unknown 對照表」對應該檔 10 個 unknown | | `50-m9-6-sdk-validation.md` §8 | 本檔結果應回填到該檔 §8.1 / §8.2 / §8.3(弱驗證部分) | | `40-b-phase-kl630-kl730-extension.md` §3.2 | 本檔「重點發現 1」確認 KneronPLUS 3.1.2 enum 列表 | | `40-b-phase-kl630-kl730-extension.md` R-FW-8 | 本檔降低該風險等級(部分 unknown 已解) | | `41-tar-firmware-handling.md` §4.4 | 本檔「發現 4」+「Unknown 對照表 A-3/A-4」確認策略 Y 唯一可行 | | `41-tar-firmware-handling.md` §5.1 表格 | 本檔「Unknown 對照表」對應該檔 #1-#10 | | `feature-firmware-management.md` AC-FW-3.5 | 本檔建議延後到 B 階段 | | `feature-firmware-management.md` 全表 | 本檔「發現 7」指出 PRD 缺「RAM-based vs Flash-based」明示 | --- ## 執行限制與不確定性聲明 **本弱驗證的限制**: 1. **無法直接讀 wheel 內 Python source**——所有結論透過 warrenchen 程式碼間接證據推得 2. **無法跑 Python REPL**——`KP_DEVICE_*` enum 值(整數)未知;只知道**名稱**存在於 SDK 3. **無 Bash**——無法 `unzip` wheel、`tar -tvf` firmware 4. **無實機**——B 類全部 + A-5 + A-6 都需要實機 **可能的錯誤來源**: 1. warrenchen 程式碼可能用了**過時 / 不推薦**的 SDK API(例:`KP_DEVICE_KL720_LEGACY` 在更新 SDK 版本可能被 deprecate);本驗證假設「warrenchen 用的 API 就是 SDK 該版本支援的 API」 2. 我們既有 visionA-local 用的是 KneronPLUS 2.0.0、warrenchen 是 3.1.2——**所有結論都是基於 3.1.2 的觀察**、2.0.0 行為可能不同 3. ctypes-level `lib.kp_*` 跟 Python `kp.core.*` wrapper 簽名可能不同(極少數情況);本驗證假設兩者語意相同 **修正路徑**:上述任何懷疑、M9-6 強驗證階段(有實機 + Bash + REPL)都能 5 分鐘內 confirm 或 refute。本弱驗證的價值不在「100% 確定」、在「**剃掉一半 unknown、把 A 階段不阻塞的部分先過、把真的需要硬體的部分留到 M9-9 / M9-10 / M9-13**」。