fbc56b9e59
同一台 Mac 有 CLI 與 Desktop 內建兩個 Claude Code,讀同一份 ~/.claude 卻不一定同結論: settings 多了 path 時 Desktop 2.1.266 忽略 inkstone marketplace、CLI 2.1.220 照常載入(c6991)。 第一版看到 path 就對整台判 ❌,在 CLI 上是假陽性。 - 逐一找 CLI(PATH)與 Desktop(最新版本,數字排序),各跑 plugin list --json,依 errors 各判各的 - 設定比對只在某一個真的報錯時當解釋+修法,永遠不單獨判 ❌ - 查不了 ⇒ ◐、離開碼 2,不講成 ✅ 或 ❌ - test-isep-doctor.sh 離線 11 條(假 claude 可執行檔);舊版跑這份 pass=1 fail=10 - test-isep-doctor-live.sh 實機 3 條:真的 CLI 2.1.220/Desktop 2.1.266,隔離 HOME 重現有/無 path,不動 ~/.claude - 盤點表與 plugin.json 描述的腳本數 62→65(這棵樹上實數) 版本號待總管定。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
65 lines
4.2 KiB
Bash
Executable File
65 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 實測:scripts/isep-doctor 對**真的** Claude Code(這台的 CLI 與 Desktop 內建那一份)判得對不對(inkstone/ISEP#150)
|
||
#
|
||
# 不動 ~/.claude:把 inkstone marketplace 與 isep 安裝紀錄複製到 mktemp 的隔離 HOME,
|
||
# 分別放「有 path」「沒有 path」兩份 settings.json,用真的可執行檔跑 doctor。
|
||
# 會打網路:只有 Claude Code 自己可能匿名讀 git.uncle6.me(Gitea),不碰 GitHub、不寫任何遠端。
|
||
#
|
||
# 期望(09-13 在 CLI 2.1.220/Desktop 2.1.266 上實測過的行為):
|
||
# 沒有 path ⇒ 兩個都 ✅,離開碼 0 (真陰性)
|
||
# 有 path、Desktop 2.1.266 ⇒ ❌ 並點名 path (真陽性)
|
||
# 有 path、CLI 2.1.220 ⇒ ✅,不因設定長相被判 ❌ (舊版 doctor 的假陽性)
|
||
# 版本不是這兩個時,該版本那一格印 SKIP(行為可能不同,不假裝驗過)。
|
||
set -u
|
||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||
R="$HOME/.claude/plugins"
|
||
[ -d "$R/cache/inkstone" ] && [ -d "$R/marketplaces/inkstone" ] || { echo "SKIP:這台沒有安裝 isep@inkstone,無從複製"; exit 0; }
|
||
|
||
CLI=$(command -v claude || true)
|
||
DESK=$(ls -d "$HOME/Library/Application Support/Claude/claude-code/"*/claude.app/Contents/MacOS/claude 2>/dev/null \
|
||
| python3 -c 'import sys,re;L=[l.strip() for l in sys.stdin if l.strip()];k=lambda p:tuple(int(x) for x in re.search(r"/claude-code/([0-9.]+)/",p).group(1).split(".") if x);print(sorted(L,key=k)[-1] if L else "")')
|
||
BINS=""; [ -n "$CLI" ] && BINS="CLI=$CLI"; [ -n "$DESK" ] && BINS="${BINS:+$BINS:}Desktop=$DESK"
|
||
[ -n "$BINS" ] || { echo "SKIP:找不到任何 Claude Code"; exit 0; }
|
||
vcli=$([ -n "$CLI" ] && "$CLI" --version | awk '{print $1}'); vdesk=$([ -n "$DESK" ] && "$DESK" --version | awk '{print $1}')
|
||
echo "CLI=${CLI:-無} ${vcli:-}|Desktop=${DESK:-無} ${vdesk:-}"
|
||
|
||
T=$(mktemp -d); trap 'rm -rf "$T"' EXIT
|
||
C="$T/home/.claude"; mkdir -p "$C/plugins/cache" "$C/plugins/marketplaces"
|
||
cp -R "$R/cache/inkstone" "$C/plugins/cache/" && cp -R "$R/marketplaces/inkstone" "$C/plugins/marketplaces/"
|
||
python3 - "$R" "$C" <<'EOF'
|
||
import json, sys
|
||
R, C = sys.argv[1], sys.argv[2]
|
||
km = json.load(open(R + "/known_marketplaces.json"))
|
||
json.dump({"inkstone": json.loads(json.dumps(km["inkstone"]).replace(R, C + "/plugins"))}, open(C + "/plugins/known_marketplaces.json", "w"))
|
||
ip = json.load(open(R + "/installed_plugins.json"))
|
||
ip["plugins"] = {"isep@inkstone": ip["plugins"]["isep@inkstone"]}
|
||
json.dump(json.loads(json.dumps(ip).replace(R, C + "/plugins")), open(C + "/plugins/installed_plugins.json", "w"))
|
||
src = {"source": "git", "url": "https://git.uncle6.me/inkstone/ISEP.git"}
|
||
json.dump({"enabledPlugins": {"isep@inkstone": True}, "extraKnownMarketplaces": {"inkstone": {"source": src}}}, open(C + "/settings.nopath.json", "w"))
|
||
src["path"] = "/Users/youlinhsieh/Documents/tech_projects/ISEP"
|
||
json.dump({"enabledPlugins": {"isep@inkstone": True}, "extraKnownMarketplaces": {"inkstone": {"source": src}}}, open(C + "/settings.path.json", "w"))
|
||
EOF
|
||
cp -R "$C" "$T/pristine"
|
||
|
||
pass=0; fail=0; skip=0
|
||
doctor() { # settings 變體
|
||
rm -rf "$C" && cp -R "$T/pristine" "$C" && cp "$C/settings.$1.json" "$C/settings.json"
|
||
OUT=$(cd "$T" && env -u CLAUDE_CODE_CHILD_SESSION HOME="$T/home" ISEP_DOCTOR_CLAUDE_BINS="$BINS" python3 "$HERE/isep-doctor" 2>&1); CODE=$?
|
||
echo "── settings=$1(exit=$CODE)"; printf '%s\n' "$OUT" | sed 's/^/ /'
|
||
}
|
||
has() { printf '%s' "$OUT" | grep -q -- "$1"; }
|
||
judge() { if eval "$2"; then pass=$((pass+1)); echo "ok $1"; else fail=$((fail+1)); echo "FAIL $1"; fi; }
|
||
|
||
doctor nopath
|
||
judge "真陰性:沒有 path → 離開碼 0、沒有 ❌" '[ "$CODE" = 0 ] && ! has "❌"'
|
||
|
||
doctor path
|
||
if [ "$vdesk" = 2.1.266 ]; then
|
||
judge "真陽性:Desktop 2.1.266 有 path → ❌ 並點名 path、離開碼 1" '[ "$CODE" = 1 ] && has "❌ Desktop 2.1.266" && has "多了 path"'
|
||
else skip=$((skip+1)); echo "SKIP 真陽性:Desktop 是 ${vdesk:-無},不是 2.1.266"; fi
|
||
if [ "$vcli" = 2.1.220 ]; then
|
||
judge "假陽性:CLI 2.1.220 有 path 但實際載入 → ✅" 'has "✅ CLI 2.1.220"'
|
||
else skip=$((skip+1)); echo "SKIP 假陽性:CLI 是 ${vcli:-無},不是 2.1.220"; fi
|
||
|
||
echo "pass=$pass fail=$fail skip=$skip"; [ "$fail" = 0 ]
|