Files
meta/tools/verify-skill-removed.sh
T
jiantw83 7dc5c32de3 fix(tools): 改用共用推導取得技能組根目錄,並補齊結束碼宣告
以 plugin 形式安裝時,腳本會落在 CLI 的 plugin 快取目錄。
六支腳本原本一律取「腳本位置的上兩層」當技能組根目錄,這時一定推錯。
這一輪例行稽核的第一步就實際踩到:不先手動設環境變數,腳本根本跑不動,
而叫用它們的技能說明也沒提要設,等於留了一個必炸的預設值。

把推導規則抽成共用腳本,依序試環境變數、從目前目錄往上找、
腳本位置的上兩層、家目錄底下的 plugins,並以 gitea.sh 在不在當判準。
marketplace 每個 domain 存取庫都帶一份,單看它會把 domain 誤判成根。
推不出來就結束並指名要設環境變數,同時列出試過的每一個候選,
呼叫端一眼看得出要設什麼。只 clone 單一存取庫的環境留了逃生門:
環境變數有設且是目錄就照用,並在錯誤輸出提醒。

順手補上語言檢查與 manifest 同步兩支腳本的結束碼宣告與環境變數說明。
沒有宣告,呼叫端只能猜;猜錯就把失敗當成功。
2026-08-31 11:11:12 +08:00

86 lines
3.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env sh
# verify-skill-removed.sh — 刪除技能後,實地檢查各 CLI 的磁碟上有沒有殘留。
#
# 用法: verify-skill-removed.sh <domain> <skill-name>
#
# 行為: 先用 jsc-cli/tools/detect-clis.sh 找出已安裝的 CLI,再逐一 grep 該 CLI 的技能快取
# 與 hook 設定,找技能名稱字面與指令形式 /jsc-{domain}:{name}。
# 未安裝的 CLI 不檢查;設定位置不存在就跳過(安靜降級,不算殘留)。
#
# 檢查位置(每個 CLI 的技能快取與 hook 設定):
# claude — ~/.claude/plugins/、~/.claude/settings.json、~/.claude/settings.local.json
# codex — ${CODEX_HOME:-~/.codex}/(config.toml 的 notify、AGENTS.md、plugins/)
# copilot — ~/.config/copilot/
# antigravity — ~/.antigravity/、~/.config/antigravity/
# kiro — ~/.kiro/、工作目錄的 .kiro/hooks/
#
# 根目錄: 交給 tools/plugins-root.sh 推導(JSC_PLUGINS_ROOT -> 從 $PWD 往上找 ->
# 腳本位置上兩層 -> $HOME/plugins)。以 plugin 形式安裝時,「腳本位置上兩層」會落在
# plugin 快取目錄,單靠它一定推錯,所以推導規則抽成共用腳本。
#
# 輸出: 檢查過的位置一行一個(stderr),殘留一行一個 {file}:{line}:{內容}(stdout)。
# 沒有殘留會印「無殘留」到 stderr,區別於「什麼都沒檢查」。
# 結束碼: 0=沒有殘留 1=有殘留 2=用法錯誤
# 3=推導不出根目錄、找不到 detect-clis.sh、沒偵測到任何 CLI,
# 或找不到可檢查的位置(**不等於乾淨**)
# 環境變數: JSC_PLUGINS_ROOT(根目錄,見 plugins-root.sh)
set -u
usage() {
echo 'usage: verify-skill-removed.sh <domain> <skill-name>' >&2
exit 2
}
[ "$#" -eq 2 ] || usage
DOMAIN=$1
SKILL=$2
[ -n "$DOMAIN" ] && [ -n "$SKILL" ] || usage
HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
. "$HERE/plugins-root.sh"
ROOT=$(jsc_plugins_root) || exit 3
DETECT=""
for d in "$ROOT/cli/tools/detect-clis.sh" "$ROOT/jsc-cli/tools/detect-clis.sh"; do
[ -f "$d" ] && { DETECT="$d"; break; }
done
[ -n "$DETECT" ] || { echo "找不到 detect-clis.sh:請先取得 jsc-cli 存取庫" >&2; exit 3; }
CLIS=$(sh "$DETECT" 2>/dev/null | cut -f1)
[ -n "$CLIS" ] || { echo "沒偵測到任何已安裝的 CLI,無處可查" >&2; exit 3; }
cli_paths() { # $1=CLI 代號;印出該 CLI 的技能快取與 hook 設定位置
case "$1" in
claude)
printf '%s\n' "$HOME/.claude/plugins" "$HOME/.claude/settings.json" \
"$HOME/.claude/settings.local.json" ;;
codex)
printf '%s\n' "${CODEX_HOME:-$HOME/.codex}" ;;
copilot)
printf '%s\n' "$HOME/.config/copilot" ;;
antigravity)
printf '%s\n' "$HOME/.antigravity" "$HOME/.config/antigravity" ;;
kiro)
printf '%s\n' "$HOME/.kiro" "./.kiro" ;;
esac
}
checked=0
hit=0
for cli in $CLIS; do
for p in $(cli_paths "$cli"); do
[ -e "$p" ] || continue
checked=$((checked + 1))
echo "檢查 $cli:$p" >&2
out=$(grep -rnI --exclude-dir=.git -e "$SKILL" -e "/jsc-${DOMAIN}:${SKILL}" "$p" 2>/dev/null)
if [ -n "$out" ]; then
printf '%s\n' "$out"
hit=1
fi
done
done
[ "$checked" -gt 0 ] || { echo "偵測到 CLI,但沒有任何設定位置存在,無處可查" >&2; exit 3; }
[ "$hit" -eq 0 ] && echo "無殘留:已檢查 $checked 個位置" >&2
exit $hit