現象
plugin-update 全程假設 plugin 位於 $MP_ROOT/plugins/$PLUGIN_NAME。對於 marketplace entry 使用 source: "./plugin"(或任何非 ./plugins/<name> 的值)的 self-hosted marketplace,這個路徑指向不存在的目錄,而每一個依賴它的偵測都會靜默回答「沒有」。
證據
plugins/harness-devtools/skills/plugin-update/SKILL.md:
- L99 — Step 0.1 的說明表格自己就寫著
PLUGIN_DIR="$MP_ROOT/plugins/$PLUGIN_NAME"
- L146 — Phase 0.3 Step 1
- L763 — Phase 2.5 Step 1
- 全檔
plugins/{plugin_name} / plugins/{name} 硬編路徑共 17 處
- 全檔沒有任何一處讀取
marketplace.json 的 plugins[].source
為什麼這是 Step 0.1 想防的那類失敗
Step 0.1 的存在理由寫得很清楚:MP_ROOT 為空時,下游每個 phase 都建立在空字串上,而**「偵測全部落空」與「檢查過沒問題」不可區分**。路徑寫死是同一個缺陷的另一個入口 —— MP_ROOT 這次是對的,錯的是接在它後面的那一段。後果一模一樣:
| Phase |
受影響 |
錯誤路徑下的結果 |
| 0.3 Step 1 |
.mcp.json / bin/*-wrapper.sh 偵測 |
IS_BINARY_BACKED=false → binary-backed 分支整條不跑 |
| 0.3 Step 2 |
plugin.json 讀 version / binary_version |
讀不到 → 三信號全空 → 可能誤判 Case A「nothing to sync」 |
| 1.5 |
Signal 1 (release asset) / Signal 2 (repo drift) |
兩個信號都不會執行 |
| 2.5 |
README 六信號 |
README 不存在 → 「跳過」 |
這些全都不報錯。使用者看到 plugin-update 跑完、綠燈,而 binary gate 從頭到尾沒驗證任何東西。
實例
PsychQuant/che-apple-mail-mcp 在 #335 之後把 plugin shell 併回 binary 的 repo,root .claude-plugin/marketplace.json 用 source: "./plugin"。實際路徑是 $MP_ROOT/plugin,skill 找的是 $MP_ROOT/plugins/che-apple-mail-mcp。2026-08-31 出貨 v3.0.0 時是人工改路徑才跑得動。
che-ical-mcp 是同一個 pilot 佈局(#335 的 CHANGELOG 明說 layout follows the che-ical-mcp pilot),推測同樣受影響 —— 未實測。
方向(不指定作法)
source 是 marketplace schema 裡既有的欄位,應該從那裡解析而不是重新約定一次。若採此路線,resolve-marketplace.sh 的 find_plugin_marketplace 回傳值可能適合從 name|root 擴成帶 plugin dir 的三元組,讓 17 個硬編點收斂到一處 —— 但那是實作決定。
無論怎麼修,偵測不到 plugin dir 時應該 abort 而非當成「沒有」,理由與 Step 0.1 相同。
Current Status
Phase: verified
Last updated: 2026-09-14 by idd-verify
Key Decisions
Scope Changes
Blocking
Commits
4449b66 85e6fc8 81ff498 初版實作(R1)
a06f236 36c2f2c bdacfd1 585320d 1972488 R2–R6(rc 分流、前導 / context 檔、possession 統一、索引重驗 + TTL)
643482e R7(plugin_manifest_path / plugin_holders、Case B 三模板、_dir_mode)
0354d05 8f609fb R8(zsh nomatch → find、fence smoke test、Step 0.1 最內層 tie-break)
16c76e4 R9(Phase 2.5 while-read、巢狀同名外層勝、binary pin 信號、Phase 1.5 Step 3)
b5e0efb R10(find_plugin_marketplace 走 holders、Step 5 移到 push 前、heredoc commit message)— idd-18-verified
現象
plugin-update全程假設 plugin 位於$MP_ROOT/plugins/$PLUGIN_NAME。對於 marketplace entry 使用source: "./plugin"(或任何非./plugins/<name>的值)的 self-hosted marketplace,這個路徑指向不存在的目錄,而每一個依賴它的偵測都會靜默回答「沒有」。證據
plugins/harness-devtools/skills/plugin-update/SKILL.md:PLUGIN_DIR="$MP_ROOT/plugins/$PLUGIN_NAME"plugins/{plugin_name}/plugins/{name}硬編路徑共 17 處marketplace.json的plugins[].source為什麼這是 Step 0.1 想防的那類失敗
Step 0.1 的存在理由寫得很清楚:
MP_ROOT為空時,下游每個 phase 都建立在空字串上,而**「偵測全部落空」與「檢查過沒問題」不可區分**。路徑寫死是同一個缺陷的另一個入口 ——MP_ROOT這次是對的,錯的是接在它後面的那一段。後果一模一樣:.mcp.json/bin/*-wrapper.sh偵測IS_BINARY_BACKED=false→ binary-backed 分支整條不跑plugin.json讀 version / binary_version這些全都不報錯。使用者看到 plugin-update 跑完、綠燈,而 binary gate 從頭到尾沒驗證任何東西。
實例
PsychQuant/che-apple-mail-mcp在 #335 之後把 plugin shell 併回 binary 的 repo,root.claude-plugin/marketplace.json用source: "./plugin"。實際路徑是$MP_ROOT/plugin,skill 找的是$MP_ROOT/plugins/che-apple-mail-mcp。2026-08-31 出貨 v3.0.0 時是人工改路徑才跑得動。che-ical-mcp是同一個 pilot 佈局(#335 的 CHANGELOG 明說 layout follows the che-ical-mcp pilot),推測同樣受影響 —— 未實測。方向(不指定作法)
source是 marketplace schema 裡既有的欄位,應該從那裡解析而不是重新約定一次。若採此路線,resolve-marketplace.sh的find_plugin_marketplace回傳值可能適合從name|root擴成帶 plugin dir 的三元組,讓 17 個硬編點收斂到一處 —— 但那是實作決定。無論怎麼修,偵測不到 plugin dir 時應該 abort 而非當成「沒有」,理由與 Step 0.1 相同。
Current Status
Phase: verified
Last updated: 2026-09-14 by idd-verify
Key Decisions
idd-18-verified=b5e0efb(13 commits,main 已 push);MEDIUM 7 條與可動手的 LOW 收成 plugin-update: #18 R10 遺留 — Step 5 unresolved 語意、commit fence pathspec / 退出碼、Phase 2.5 信號 4 與 SKIPPED 消毒 #24(Conflict Class C,與 plugin-update: Phase 0.3 與 Phase 0.5 可對同一次執行給出互相矛盾的裁決 #19 / plugin-update: binary-backed detection misses binaryVersion, non-wrapper.sh wrappers, missing marketplace version, and the post-release pin bump; Phase 5 never verifies the binary #22 同檔)resolve_plugin_dir/find_plugin_marketplace三元組 /plugin_holders/plugin_manifest_path)、單一持有判準、私有純資料 context 檔(索引重驗 + TTL)、每個 fence 帶前導且 git 動作只在 fence 內跑、巢狀同名 marketplace 外層勝、fence 在 bash 與 zsh 下各實跑(test-plugin-update-fences.sh36 條;resolver 139 條)find_plugin_marketplace三元組為 breaking,兩個直接消費者同批更新;版本 bump 留到 plugin-update: Phase 0.3 與 Phase 0.5 可對同一次執行給出互相矛盾的裁決 #19 / plugin-update: binary-backed detection misses binaryVersion, non-wrapper.sh wrappers, missing marketplace version, and the post-release pin bump; Phase 5 never verifies the binary #22 之後name|root|plugin_dir+resolve_plugin_dir,直接 chain 到 idd-implement --no-prfind_plugin_marketplace只以plugins/<name>目錄存在判定命中、從不讀plugins[].source;plugin-update/SKILL.md另有 18 處硬編路徑find_plugin_marketplace);Conflict Class = C(與 plugin-update: Phase 0.3 與 Phase 0.5 可對同一次執行給出互相矛盾的裁決 #19 / plugin-update: binary-backed detection misses binaryVersion, non-wrapper.sh wrappers, missing marketplace version, and the post-release pin bump; Phase 5 never verifies the binary #22 共用 SKILL.md 與 resolver,序列化,本 issue 先做)Scope Changes
Blocking
Commits
4449b6685e6fc881ff498初版實作(R1)a06f23636c2f2cbdacfd1585320d1972488R2–R6(rc 分流、前導 / context 檔、possession 統一、索引重驗 + TTL)643482eR7(plugin_manifest_path/plugin_holders、Case B 三模板、_dir_mode)0354d058f609fbR8(zsh nomatch → find、fence smoke test、Step 0.1 最內層 tie-break)16c76e4R9(Phase 2.5 while-read、巢狀同名外層勝、binary pin 信號、Phase 1.5 Step 3)b5e0efbR10(find_plugin_marketplace走 holders、Step 5 移到 push 前、heredoc commit message)— idd-18-verified