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>
24 KiB
24 KiB
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 到實機
- 不能解壓 wheel binary(沒 Bash /
- 可用證據來源:
- warrenchen prototype(
/tmp/web_academy_prototype/)的 Python source code - visionA-local 既有
server/scripts/kneron_bridge.py(看我們現在用了哪些 kp API) - 既有研究檔 §00-§42
- warrenchen bundled wheel filename pattern:
KneronPLUS-3.1.2-py3-none-any.whl - 既有 visionA-local wheel:
KneronPLUS-2.0.0-py3-none-any.whl(macOS/Linux)+KneronPLUS-3.1.2-py3-none-any.whl(Windows)—— wheel 版本三平台不一致(重要發現)
- warrenchen prototype(
結論(TL;DR)
- KneronPLUS 3.1.2 確認支援 KL630/KL730 enum——warrenchen
main.pyL433-447 直接用kp.ProductId.KP_DEVICE_KL630/KL730/KL830、運作中、enum 存在無疑。 update_kdp_firmware_from_filesAPI 在 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。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(待強驗證確認)。load_firmware_from_file只接受兩個 .bin 路徑(scpu, ncpu)、不接受 .tar——warrenchenFirmwareLoadRequestschema 強證據:scpu_path: str+ncpu_path: str、無tar_path欄位。策略 Z(直接餵 .tar 給 SDK)不可行。- 沒有
load_firmware_from_tar/update_kdp_firmware_from_tarAPI——warrenchen 完全沒有用、且若存在會出現在FirmwareLoadRequest或legacy_plus121_runner.py。策略 Y(build time 解壓 .tar 找 .bin)是唯一可行解。 - 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_upgradefor KL630/KL730 時、沒有 reference 實作可抄、要自己根據 KneronPLUS SDK 推。 - 重大發現:visionA-local wheel 三平台版本不一致——macOS/Linux 是
KneronPLUS-2.0.0、Windows 是KneronPLUS-3.1.2。2.0.0 是否含KP_DEVICE_KL630/KL730enum 無法靜態確認——KP_DEVICE_KL720_LEGACY在 3.1.2 確認存在(warrenchen L432)但 2.0.0 不確定。強驗證必跑:在 macOS + Linux 上實際import kp; print(kp.ProductId.KP_DEVICE_KL630)看是否存在。 - 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 啟動時實機強驗
- 理論上可行(SDK API 都在、enum 都在、
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 直接讀)
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)
# 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、warrenchenlegacy_plus121_runner.pyL273-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)
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 接受
# 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
# 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 的使用模式
# 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_loadendpoint 走這條)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——理由:
- 無 warrenchen reference 實作(design risk 高)
- wheel 三平台不一致、A 階段要做 KL630/KL730 升降版必先處理 wheel 升級(額外 1-1.5 人天 + regression 風險)
- 沒實機根本沒法 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 -tvfinspect)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」明示 |
執行限制與不確定性聲明
本弱驗證的限制:
- 無法直接讀 wheel 內 Python source——所有結論透過 warrenchen 程式碼間接證據推得
- 無法跑 Python REPL——
KP_DEVICE_*enum 值(整數)未知;只知道名稱存在於 SDK - 無 Bash——無法
unzipwheel、tar -tvffirmware - 無實機——B 類全部 + A-5 + A-6 都需要實機
可能的錯誤來源:
- warrenchen 程式碼可能用了過時 / 不推薦的 SDK API(例:
KP_DEVICE_KL720_LEGACY在更新 SDK 版本可能被 deprecate);本驗證假設「warrenchen 用的 API 就是 SDK 該版本支援的 API」 - 我們既有 visionA-local 用的是 KneronPLUS 2.0.0、warrenchen 是 3.1.2——所有結論都是基於 3.1.2 的觀察、2.0.0 行為可能不同
- ctypes-level
lib.kp_*跟 Pythonkp.core.*wrapper 簽名可能不同(極少數情況);本驗證假設兩者語意相同
修正路徑:上述任何懷疑、M9-6 強驗證階段(有實機 + Bash + REPL)都能 5 分鐘內 confirm 或 refute。本弱驗證的價值不在「100% 確定」、在「剃掉一半 unknown、把 A 階段不阻塞的部分先過、把真的需要硬體的部分留到 M9-9 / M9-10 / M9-13」。