visionA/local-tool/docs/autoflow/04-architecture/build-troubleshooting.md
jim800121chen 9397a4d31f docs: 新增三平台 build troubleshooting 參考
把 M10 這輪三平台 build 踩的雷整理成 troubleshooting 文件,供未來
build 安裝包時參考。

涵蓋 9 條逐項 troubleshooting(統一格式:症狀 → 根因 → 為什麼發生
→ 解法 → 如何根治)、快速症狀索引表、5 條橫向教訓、KneronPLUS
2.0.0 vs 3.1.2 版本相容附錄、build 驗收 checklist。

核心教訓:症狀常不指向根因(Error 12 是 input size、pip 秒退是 wheels
多版本、中文亂碼是 stdio code page),macOS 開發環境測不到大量
Windows-only 問題(編碼、DLL 路徑、SDK 版本差異)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 09:08:13 +08:00

26 KiB
Raw Permalink Blame History

Build Troubleshooting — visionA-local

這份文件的用途:記錄 visionA-local 打包安裝檔macOS / Windows / Linux時實際踩過的雷 讓下次遇到同樣症狀能快速定位,而不是重新 debug 一輪。

目標讀者:未來要在 Windows / Linux build 這個專案安裝包的開發者(可能是你自己,也可能是團隊成員)。

這不是 build 教學。build 流程本身看 build-pipeline.mdMakefile 骨架、vendor 目錄、CI 策略)。 這份是它的 troubleshooting 補充:症狀 → 根因 → 為什麼會發生 → 解法 → 如何預防/根治

紀錄來源2026-07 這輪M10 classification + 特規打包 + 三平台實機 build踩的雷 每條都對到 progress.md 或實際 code 的 檔案:行號。若與現況不符,以 code 為準。


快速症狀索引表

先在這張表找你看到的症狀,跳到對應章節。症狀常常不指向真正的根因——這正是這份文件存在的理由。

你看到的症狀 可能的雷 跳到
裝置 reset 後 load_model Error code 24、停在 KDP2 Loader 開發模式 dist/scripts/firmware/ §1
前端顯示「載入模型失敗」、terminal 出現 darwin_usb.c:584 / SIGABRT 除錯時 curl 與 UI 搶同一顆 USB §2
Windows buildgo: command not found / wails: command not found / pnpm not found(明明裝了) MSYS2 login shell 重建 PATH §3
Build 後置檢查失敗「預期 2 個 .nef實際 8 個」 copy_bundled_data 沒清空目標、殘留舊 .nef §4
Windows 推論 KP_ERROR_INVALID_PARAM_12Error 12 input size 用了使用者亂填的 declared 值 §5
每次啟動都「Python 相依未通過」但又不重裝,怎樣都好不了 venv 半套安裝、只檢查 python.exe 存在就跳過 §6
明明環境是好的卻被判「Python 相依驗證失敗」擋住啟動 健康檢查 probe 沒補 Windows DLL 搜尋路徑 §7
App 一啟動 pip 就秒退 ResolutionImpossiblecertifi ×3 之類) vendor wheels 累積多版本 §8
Windows 中文標籤亂碼「布」→「撣<E3808C>」、log 出現 <EFBFBD> Python stdio 綁 cp950 而非 UTF-8 §9

如果症狀不在表上,先讀 §10 共通教訓——很多雷的「表面症狀」都不指向根因。


環境前置需求(三平台)

打包前的一次性環境安裝,用 bootstrap 腳本,不要手動裝:

平台 腳本 裝什麼
Windows scripts/bootstrap-windows.ps1 winget 裝 git / go / node / pnpm / python / MSYS2(提供 bash + make/ Inno Setup + wails
Linux scripts/bootstrap-linux.sh apt 裝 go 1.22.5 / node 20 / pnpm / wails + GTK/WebKit/libusb dev headers
macOS (手動) go / node / pnpm / wails / brew install create-dmgDMG 美化,選用)

三平台都需要 make vendor-sync 先把第三方二進位Python runtime / wheels / ffmpeg下載到 vendor/

⚠️ Windows 特別注意make 在 Windows 上是透過 C:\msys64\usr\bin\bash.exe 執行的Windows 沒有原生 make 這帶來 §3 的 PATH 坑。詳見該節。


逐條 Troubleshooting

§1 開發模式資源不同步 → 裝置 reset 後 load_model Error 24

症狀

  • 裝置首次連線、reset 後,load_modelError code 24
  • Python bridge 卡在 KDP2 Loader 狀態、進不到 KDP2 Comp
  • 只在手動開發模式(dist/scripts/)發生,打包出來的安裝包沒這問題。

根因

  • 開發模式下 dist/scripts/ 需要同時含 kneron_bridge.py + firmware/ + drivers/dist/data/ 需含 models.json.nef
  • 曾經只手動複製了 kneron_bridge.py漏掉 firmware/ → 裝置 reset 後 bridge 重啟時找不到 firmware → 停在 Loader → load_model Error 24

為什麼會發生

  • 手動同步「就複製那個我改到的檔案」很直覺,但 bridge 執行期會去讀 firmware/drivers/ 這些不會每次都動、容易被忘記的相依資源。
  • 打包流程之所以沒事,是因為 Makefile 三平台都用整包搬(cp -R server/scripts/* / find | cp 整包),不是逐檔挑。

解法

  • 開發模式同步時,dist/scripts/ 一律帶齊 kneron_bridge.py + firmware/ + drivers/dist/data/ 帶齊 models.json + .nef。不要只複製「這次改到的那個檔」。

如何預防 / 根治

  • 走打包流程驗證而不是手動同步:make payload-macosprogress.md L413 實跑驗證過 firmware/drivers 都在)。
  • 已寫入 memory~/.claude/projects/-Users-jimchen-visionA/memory/project_local_tool_dev_env.md
  • 來源progress.md L409-414。

§2 除錯時 curl 戳 flash 與 UI 搶同一顆 USB → SIGABRT

症狀

  • 使用者端顯示「載入模型失敗」。
  • terminal 出現 libusb 的 assertdarwin_usb.c:584,程式 SIGABRT 直接掛掉。

根因

  • 除錯時用 curl 觸發 flashload model同時使用者還在用 UI 操作同一顆裝置 → 兩個行程同時對同一個 USB endpoint 下命令 → libusb 在 macOS 上直接 assert / abort。

為什麼會發生

  • USB 裝置不是可多路複用的資源。KneronPLUS SDK / libusb 沒有替你做互斥;兩個 client 同時搶就炸。

解法 / 預防

  • 除錯期間不要碰裝置——要嘛用 curl 手動測、要嘛用 UI 測,不要兩個同時來。
  • 這不是 code bug是除錯操作紀律。記住這個 assert 訊息(darwin_usb.c:584),下次看到就知道是雙頭搶 USB不用往 code 裡挖。
  • 來源progress.md L412。

§3 bootstrap-windows 的 MSYS2 PATH → Go / wails / node / pnpm 找不到

症狀

  • Windows build 時,go / wails / node / pnpm 明明用 winget 裝好了,跑 make 卻報 command not found

根因

  • Windows 沒有原生 make本專案透過 C:\msys64\usr\bin\bash.exe -llogin shell)來跑 Makefile。
  • login shell 啟動時會重跑 /etc/profile把 PATH 整個重建成 MSYS2 自己的一套Windows 上用 winget 裝的工具目錄就這樣被洗掉了。
  • MSYS2_PATH_TYPE=inheritbootstrap 有設,bootstrap-windows.ps1:74只影響 MSYS2 自己的 shell 啟動器msys2.exe / mingw64.exe);直接呼叫 bash.exe -l 時它不生效。

為什麼會發生

  • inherit 的作用範圍與「直接呼叫 bash.exe -l」的實際入口不重疊是一個很容易誤解的設定。這也是為什麼 Inno Setup 呼叫、Python 呼叫本來就必須各自手動 export PATH。

解法

  • 跟 Inno Setup 一樣,明確把工具目錄轉成 MSYS2 路徑格式(C:\foo/c/foo)後再 export,補在 $PATH 之前。
  • 實作見 bootstrap-windows.ps1:73-113(註解完整說明)、:200(去重合併成單一 export避免多行 export 互相覆蓋)、:284-294

如何預防 / 根治

  • 任何要在 MSYS2 bash.exe -l 下被找到的工具,都不能依賴 inherit,一律顯式 export 轉譯後的 MSYS2 路徑。
  • 來源:bootstrap-windows.ps1:73-113、progress.md L1401M7 同型坑的前身)。

§4 copy_bundled_data 不冪等 → 「預期 2 個,實際 8 個」

症狀

  • Build 後置檢查失敗:!! ERROR: 預期 2 個 .nef實際 8 個 !!build 中止。

根因

  • payload-windows / payload-linux 刻意不 rm -rf 整個 payload/<os>/(因為 build-server-* 已先把 binary 放進 bin/),所以前次 build 的 data/ 殘留會留著。
  • 白名單機制M5-a、BUNDLED_NEFS 只留 2 個 .nef上線前舊 build 會把 8 個 .nef 全複製進去。升級到白名單版本後再 build就變成「新複製 2 個 + 殘留 6 個 = 8 個」,被後置檢查擋下。
  • payload-macos 沒踩到,只是因為它有 rm -rf payload/darwin

為什麼這個後置檢查是「對的」

  • installerinstaller/windows/visiona-local.iss)是用 data\* + recursesubdirs 整包收,殘留什麼就出貨什麼。所以「數 .nef 個數不符就 fail」是防止安裝包偷偷多帶不該帶的模型——這個 fail-loud 檢查要保留。

解法

  • copy_bundled_data helper 先清空整個目標 data 目錄再複製(步驟 (a)),確保重複執行結果一致、不受既有內容影響。
  • 為什麼清整包而不是只清 nef/:目標目錄內容 100% 由這個 helper 產生Makefile 中只有這裡寫入 payload/<os>/data/),沒有其他來源需要保留;只清 nef/ 的話,未來從 server/data/ 移除的其他檔案殘留仍會被 installer 整包打包出貨。清整包才是真正冪等。
  • 實作 + 完整註解見 Makefile:39-118define copy_bundled_data)。

如何預防 / 根治

  • helper 內建 fail-loud 後置檢查:白名單缺檔直接 failMakefile:104-108)、複製後驗 models.json 存在(:101-103+ .nef 數量 == 白名單長度(:113-116)。
  • 不用 rsyncWindows CI 跑在 Git Bashwindows-2022 + shell: bash),該環境沒有 rsync → 一律用 POSIX find / cpMakefile:71-72)。
  • 來源:Makefile:39-118、progress.md L112-124。

§5 input size 優先序錯 → Windows 推論 Error 12

症狀

  • Windows 上推論回 KP_ERROR_INVALID_PARAM_12Error 12
  • 同一個模型在 macOS 上正常。

根因

  • input size 的來源可信度排序,declared使用者在上傳表單手填的值不能排在檔名解析之前
  • 上傳表單的 inputSize 欄位長期沒有實際作用,使用者是「隨手填」的(實際案例:填 640×640模型其實是 224×224
  • KneronPLUS 3.1.2Windows不再提供 2.0.0macOSshape_onnx 屬性SDK 這層在 Windows 直接落空 → 於是垃圾 declared 值成為實際採用值,送進 NPU 得到 Error 12。
  • 檔名的 wNNNhNNN 是模型編譯工具鏈產生的,沒有人為亂填空間,明確解析出來時比 declared 可信

為什麼是 Windows 才炸

  • 見 §附錄「KneronPLUS 版本相容性」macOS 用 2.0.0、Windows 用 3.1.2shape 欄位在 3.x 搬進巢狀 unionTensorDescriptor.tensor_shape_info.data),舊寫法 getattr(node, "shape_onnx") 在 3.1.2 拋 AttributeError 被靜默吃掉 → SDK 來源落空 → 掉到 declared。

解法

  • input size 可信度排序改為:SDK(0) → filename(1) → declared(2) → known-model-id(3) → default(4)。declared 降到第 3。
  • 常數與完整根因註解見 kneron_bridge.py:351-371INPUT_SIZE_SOURCE_RANK)。
  • 逐軸解析(不再沿用單一純量 _model_input_size,因為模型輸入不保證正方形):kneron_bridge.py:159-193
  • 相容兩版 SDK 的 shape 讀取(先試 3.x 巢狀 tensor_shape_info、再退平鋪欄位):kneron_bridge.py:479-523

如何預防 / 根治

  • 實機驗收時 grep log 印出的 input size sourcekneron_bridge.py:347-349 說明這是唯一能一眼看出尺寸怎麼來的線索)——尺寸錯掉時 NPU 不一定報錯,可能只是安靜給錯結果。
  • ⚠️ 這是 §10「湊巧正確」教訓的實例舊版檔名猜 224 湊巧對,改成「更可信」的 declared 反而錯。
  • 來源:kneron_bridge.py:345-376, 479-523

§6 venv 半套安裝 → 永久卡住、怎樣都好不了

症狀

  • 每次啟動都跑「Python 相依驗證未通過」,但又不重裝、也沒有提示,怎樣都好不了。
  • 只能手動刪掉 runtime/venv 才能恢復。

根因

  • 舊邏輯只檢查 python.exevenv/Scripts/python.exevenv/bin/python3存在就跳過安裝。
  • 但「python 執行檔存在」不等於「相依裝好了」pip install 中途失敗(斷網 / 磁碟滿 / 防毒攔截)會留下 venv 與 python.exe 都在、但 import kp 失敗的半套環境
  • 於是每次啟動都「看到 python.exe → 跳過安裝 → 但 import 失敗」,永久卡死且無提示。

解法

  • venv 已存在的日常啟動路徑改為「驗健康、必要時嘗試修復」:reuseExistingVenvapp.go:1078-1103)。
  • venv 在但相依看起來壞了 → 只補裝 wheels、不整個重建 venv(重建要重解壓 ~100MB tarball而失敗幾乎都出在 pip 階段):app.go:1091-1093
  • 修復失敗時記錄 warning 但不阻斷啟動(見 §7改以現有 venv 繼續:app.go:1096-1101

如何預防 / 根治

  • 狀態檢查要驗「真的能用」而非「檔案在」——這是 §10 的橫向教訓。
  • 快路徑用標記檔 venv-ready.txt 記錄「wheels 已成功裝完 + 當前 wheels 指紋」,指紋不符才真的跑一次 import 驗證(app.go:1105-1152)。
  • 來源:app.go:995-1103、progress.mdM4 之後的 fix

§7 健康檢查阻斷啟動(自造 regression→ 健康的 venv 被判壞、擋住啟動

症狀

  • 環境明明是好的bridge 實際能跑、能掃到裝置app 卻因「Python 相依驗證失敗」擋住啟動。

根因(這是修 §6 時自己造成的 regression

  • §6 的健康檢查 probe 裸跑 python -c "import kp"沒有補 Windows 的 DLL 搜尋路徑
  • kp 在 import 時就會 ctypes.CDLL 載入 kp/lib 下的 native DLLlibkplus / libusb-1.0 / libwdi + MinGW runtime共 6 個。Windows 上這些 DLL 不在預設搜尋路徑、必須先 add_dll_directory
  • 真正跑 bridge 時 kl720_driver.gostartPython()platform_windows.go 的 driver 安裝腳本做這件事,但 probe 沒做 → 健康的環境也 import 失敗 → 被判壞掉 → 擋住啟動。

解法

  • probe 的環境要盡量貼近「真正跑 bridge 的環境」:pythonProbeScript 加一段 preamble先把 site-packages/*/lib 掛進 PATH + os.add_dll_directory 再 importapp.go:1182-1205)。
  • 更重要的原則:健康檢查絕不可以成為啟動的阻斷點。 完整理由見 app.go:999-1016
    1. 這個 probe 會誤判(環境貼合度永遠不可能 100%)。
    2. 就算真的壞了,讓 bridge 自己回報「掃不到裝置」這類具體錯誤,比在啟動前用一個間接的 probe 攔死更好——kneron_bridge.py 本來就把 import kp 失敗當可降級的情況處理。
  • 型別設計落地這個原則:reuseExistingVenv 沒有 error 回傳值app.go:1078-1081)——型別本身就保證了「健康檢查不會阻斷啟動」。

如何預防 / 根治

  • 加任何「啟動前健康檢查」時,先問:檢查失敗會不會擋住啟動?如果會,它就有能力誤殺健康環境。健康檢查應該是「發警告 + 嘗試修復」,不是 gate。
  • 來源:app.go:999-1016, 1078-1103, 1154-1205

§8 wheels 多版本 → pip ResolutionImpossible、app 一啟動就秒退

症狀

  • App 首次啟動安裝依賴時pip 在 ~2 秒內 ResolutionImpossible 失敗,使用者完全無法啟動。
  • vendor 目錄裡同一套件有多顆(如 certifi ×3numpy ×2idna ×2)。

根因

  • vendor-wheels*pip download --dest,而 pip download 只「補下載缺的」、不移除舊版
  • upstream 每發一次新版,vendor/wheels/<os> 就多留一顆 whl → 實機累積成 16 顆(正常應為 9 顆)。
  • 這些多版本原封不動被 payload-* 複製進安裝包 → app 啟動 pip install a.whl b.whl ... 同時收到 certifi 2026.2.252026.6.17 → 直接 ResolutionImpossible。
  • debug 成本放大:這個 pip 錯誤還被 Makefile 的 Auto 分支吞掉(|| echo WARN),導致三輪來回都拿不到線索。

解法(兩層都要)

  • 源頭clean_wheels_dir helper 在 vendor-wheels* 前先清空並重建 vendor/wheels/<os>/,確保冪等、不累積多版本(Makefile:143-166,完整事故迴歸註解在 :121-142)。
  • 救援app 端 selectLatestWheelPerPackage 對每個套件只保留版本最高的一顆再交給 pipapp.go:1314-1325+),能救「已出貨」的舊安裝包。
  • 兩層都要有:源頭杜絕讓新安裝包乾淨、救援讓舊安裝包也能自癒。

如何預防 / 根治

  • 版本比較用逐段整數比較的簡化 PEP 440compareWheelVersionsapp.go:1282-1312);套件名依 PEP 503 正規化,讓 opencv_python_headlessopencv-python-headless 視為同套件(normalizeDistNameapp.go:1255-1271)。
  • 錯誤不要被吞掉:這條的三輪 debug 成本就是 pip 錯誤被 || echo WARN 吞掉造成的。詳見 §10。
  • 來源:Makefile:121-166app.go:1207-1325、progress.md L135-136。

§9 Windows 中文亂碼 → 標籤「布」變「撣<E3808C>

症狀

  • Windows繁中上 classification 標籤亂碼「布」變「撣<E3808C>」。
  • stderr log 的中文與 em dashU+2014出現 <EFBFBD>(如 <EFBFBD>X SDK did not report)。

根因

  • Windows 的 Python 把 stdio 綁到「系統 ANSI code page」而非 UTF-8。繁中 Windows 的 ANSI code page 是 cp950
  • bridge 的 JSON-RPC 兩個方向不對稱
    • Go → Python (stdin)Go 的 encoding/json escape 非 ASCII{"labels":["布"]} 在 wire 上是 raw UTF-8 e5 b8 83。以 cp950 解碼得到「撣」+ U+FFFD截圖的亂碼嚴格模式下直接 UnicodeDecodeError 讓整個 bridge 掛掉。
    • Python → Go (stdout)json.dumps 預設 ensure_ascii=True,中文被 escape 成 \uXXXX 純 ASCII所以這條「目前剛好沒壞」——但那是隱性依賴任何人加上 ensure_ascii=False 就會壞。
    • stderr_log() 的中文與 em dash 現在就會壞。

解法

  • _force_utf8_stdio() 把 stdin / stdout / stderr 一律 reconfigure(encoding="utf-8", errors="replace")kneron_bridge.py:22-71),不理會系統預設編碼。
  • 在 module import 時就呼叫kneron_bridge.py:71),不是在 main() 裡——必須早於任何 I/Omain()os.dup() stdout、import 期間的例外也走 stderr
  • errors="replace" 而非 strict:這是診斷 log 通道與協定通道,遇到極端無效位元組寧可看到一個 U+FFFD 也不要讓整個 bridge 因一行 log 而崩潰bridge 掛掉 = 裝置失聯,比壞字元嚴重)。

如何預防 / 根治

  • 把「stdout 是 UTF-8」變成顯式契約而非巧合(連目前沒壞的 stdout 方向也一併綁定)。
  • ⚠️ PYTHONUTF8PYTHONIOENCODING 管的範圍不同:前者是整個 Python 的 UTF-8 mode含檔案系統編碼等、後者只管 stdio 的編碼。這裡用程式內 reconfigure 是最直接、不依賴環境變數是否被正確傳入的做法。
  • 測試釘死:server/scripts/test_kneron_bridge_encoding.py
  • 來源:kneron_bridge.py:22-71

§10 共通教訓(橫向 pattern

這節比逐條 bug 更有價值——上面 9 個雷裡反覆出現的幾個 pattern下次寫 code / debug 時記住這些,能少踩一半。

10.1 macOS 開發 ≠ Windows 實機

好幾個雷都是「macOS 有、Windows 沒有」或「兩邊行為不同」造成的。macOS 上測不到、只有 Windows 實機才會爆的類別:

類別 macOS Windows 踩到的雷
stdio 編碼 預設 UTF-8 預設 cp950繁中 ANSI code page §9 中文亂碼
native DLL 搜尋路徑 dyld可用 ctypes 絕對路徑預載) add_dll_directory、不在預設路徑 §7 健康檢查誤殺
KneronPLUS SDK 版本 2.0.0(有 shape_onnx 3.1.2shape 搬進巢狀 union §5 input size Error 12
shell / make 原生 bash + make MSYS2 login shell 重建 PATH §3 工具找不到
既有環境 開發機常有現成工具 乾淨機、什麼都要 bootstrap §3 / §4

原則:任何「編碼 / DLL 路徑 / SDK 版本 / code page / shell」相關的東西不能只在 macOS 驗,一定要 Windows 實機或至少想清楚兩邊差異。

10.2 「檔案存在」≠「可用」

§6venv 半套安裝)和 §7健康檢查都栽在這。

  • venv 只檢查 python.exe 存在就跳過安裝 → 半套環境永久卡死。
  • 狀態檢查要驗**「真的能用」**(實際 import / 實際跑一次),而非「檔案在」。
  • 但驗「能用」時要注意 §7 的教訓:驗證環境要貼近真實執行環境,否則會誤殺健康的環境;而且健康檢查不能是啟動阻斷點

10.3 錯誤被吞掉會讓 debug 成本爆炸

§8wheels 多版本)的三輪來回,根因是 pip 錯誤被 Makefile 的 || echo WARN 分支吞掉,拿不到真正的錯誤訊息。

  • 吞錯誤 = 把「一次就能定位」變成「三輪還在猜」。
  • fail-loud 優於 fail-silent。§4 的後置檢查(數 .nef 個數不符就直接 fail就是正面教材——它讓「安裝包偷偷多帶模型」在 build 期就爆,而不是等出貨後使用者才發現。
  • 對照 §5input size 錯掉時 NPU 不報錯只給錯結果——這種「靜默失敗」最貴,所以要靠 log 印出 source 當唯一線索。

10.4 「湊巧正確」的行為改動要格外小心

§5input size 優先序)是經典案例:

  • 舊版用檔名猜測,某些模型湊巧猜到 224、剛好對。
  • 改成「看起來更可信」的 declared使用者手填值反而錯——因為使用者是隨手填的。
  • 教訓當你把一個「能動但你覺得不夠嚴謹」的邏輯改成「更正確」的版本時先確認新來源真的更可信。「更正式的欄位」不代表「更可信的值」——declared 是正式欄位、但值是垃圾。

10.5 兩層防護(源頭 + 救援)

§8 的解法是兩層都做:clean_wheels_dir 從源頭杜絕(新安裝包乾淨)+ selectLatestWheelPerPackage 救援(舊安裝包自癒)。

  • 只做源頭 → 已出貨的舊安裝包救不了。
  • 只做救援 → 每個新安裝包都帶著髒 vendor 出貨、依賴 app 端補救。
  • 涉及「已出貨產物」的問題,通常源頭與救援都要有。

§附錄 AKneronPLUS 版本相容性

三平台的 KneronPLUS wheel 版本不一致,這是好幾個雷的隱形根因。寫任何碰 SDK 的 code 時必讀。

平台 KneronPLUS wheel 版本 影響
macOS 2.0.0 TensorDescriptor 有平鋪的 shape_onnx / shape_npu 屬性
Linux 2.0.0 同上
Windows 3.1.2 shape_onnx 屬性shape 搬進巢狀 tensor_shape_info.dataV1/V2 unionDLL 需求更嚴

具體差異與注意事項

  1. shape 欄位位置不同(→ §5 Error 12

    • 2.0.0node.shape_onnx / node.shape_npu 直接可讀。
    • 3.1.2node.tensor_shape_info.versionModelTensorShapeInformationVersion+ .dataTensorShapeInfoV1shape_onnx/shape_npuTensorShapeInfoV2 只有 .shapedocstring 明寫是 ONNX shape
    • 舊寫法 getattr(node, "shape_onnx") 在 3.1.2 拋 AttributeError → 被 except 靜默吃掉 → SDK 這層以為「模型沒帶 shape」其實是讀錯欄位。
    • 相容兩版的讀法見 kneron_bridge.py:479-523(先試巢狀、再退平鋪)。
  2. native DLL 需求(→ §7 健康檢查誤殺)

    • import kp 在 Windows 會載入 kp/lib 下的 native DLLlibkplus / libusb-1.0 / libwdi + MinGW runtime共 6 個),不在預設搜尋路徑 → 需 add_dll_directory
    • macOS 走 dyld可用 ctypes 絕對路徑預載(_preload_kneron_dylibs_macoskneron_bridge.py:74+)。
  3. wheel 三平台版本不一致本身是風險progress.md M9-6 findings L587

    • 若未來要加 KL630/KL730 等新晶片支援macOS/Linux 的 2.0.0 wheel 沒有對應 enum必須先升 wheel。
    • update_kdp_firmware_from_files 在 3.1.2 Python wrapper 中不存在warrenchen 是 ctypes 直打 .so C symbol這類 API 差異在跨版本時要逐一確認。

原則:任何讀 SDK 結構shape / enum / API 簽章)的 code都要同時對 2.0.0 與 3.1.2 驗,或明確寫成「先試新版結構、失敗再退舊版」的相容寫法。


§附錄 BBuild 完驗收 Checklist

Build 完一個安裝包後,至少驗這些(每項標了對應的雷,避免重蹈覆轍):

  • .nef 數量正確:打包版(不是開發模式)確認只帶白名單的 2 個 .nefFCOS Detection / Tiny YOLOv3),不是 8 個。→ §4 (開發模式驗不出來:server/data/nef/ 8 個都在、過濾器只濾「檔案不存在」,開發模式會顯示 7 個模型。M5 必須用打包版驗、progress.md L206。
  • models.json 有進安裝包:啟動後 /api/models 回非空、log 印 Loaded N built-in models(不是 0
  • 中文顯示正常Windows 繁中機classification 標籤、log 的中文都不亂碼。→ §9
  • input size source 正確:實機推論後 grep log 的 input size source確認不是掉到 declared / default 撿到垃圾值Windows 上尤其要看。→ §5
  • 推論不報 Error 12 / Error 24Windows 推論不 Error 12§5、裝置 reset 後 load_model 不 Error 24§1
  • Python venv 健康:全新機器首次啟動能自動裝好 wheels不 ResolutionImpossible §8且啟動不被健康檢查誤擋§7
  • driver 綁定Windows 上 KneronPLUS native DLL 能被載入(import kp 成功、掃得到裝置)。→ §7 / 附錄 A
  • Wails 視窗確認開 app window 確認主 UI 是 Next.js 而非 splash / installer wizard / 白畫面progress.md L1602 的歷史教訓M1 只用瀏覽器連 localhost 驗、沒開 window讓 wizard 殘留混過 M1-M6

驗收原則不要只驗「server 有回應」——很多雷§1 / §4 / §5 / §9/api/health 200 的情況下照樣存在。要驗到「真的能推論 + 顯示正確」。


相關文件

  • build-pipeline.md — Makefile 骨架、vendor 目錄結構、CI 策略、版本號管理build 流程本體)。
  • progress.md.autoflow/progress.md)— M10 各段開發紀錄與踩坑細節的一手來源。
  • memory~/.claude/projects/-Users-jimchen-visionA/memory/project_local_tool_dev_env.md — 開發模式資源同步坑。