fix(meta): 補齊稽核缺失並修掉護欄失效
What:依 jsc-meta:skill-check 的稽核結果修正技能與工具——補上每個步驟的可檢核完成條件、 把留在內文的標準輸入輸出流程下放 tools/、修正查表與退碼路由造成的誤判。 Why:稽核發現這些缺失會讓技能在實際執行時走錯分支或靜默通過。 完成條件缺漏是最常被違反的一項;退碼誤判與查表錯誤則會讓良性狀況被當成失敗。 How:逐項對照 references/guidelines.md 的審核檢查清單修正,新增的工具都有 documented exit codes,並以真實執行驗證每條路徑。 Who:jsc-meta:skill-check 例行稽核(2026-08-25)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,15 +4,28 @@
|
||||
# 用法: find-skill-refs.sh <domain> <skill-name>
|
||||
#
|
||||
# 掃描樣式:
|
||||
# 1. 技能名稱字面 {skill-name}
|
||||
# 1. 技能名稱字面 {skill-name}——**純子字串比對**,不看邊界。
|
||||
# 所以短名稱也會命中「名稱+後綴」的其他技能名,以及純敘述文字裡的同一個詞。
|
||||
# 這是故意的:盤點寧可多列,漏一個引用會讓刪除技能少改檔案。
|
||||
# 呼叫端必須逐檔看過命中內容再判斷,不可把清單當成「一定要改的檔案」。
|
||||
# 2. 指令形式 /jsc-{domain}:{skill-name}
|
||||
# 這兩個樣式已涵蓋其他 SKILL.md 的引用、domain README 的「Skills 目錄」小節、
|
||||
# plugins/meta 兩份 marketplace.json 與其在各 domain 存取庫的同步副本、tools/ 腳本、
|
||||
# jsc-hooks 接線等位置——只要檔案裡出現技能名稱或指令形式就會被列出。
|
||||
#
|
||||
# 掃描範圍: /root/plugins 底下所有 domain 存取庫,排除 .git 目錄。
|
||||
# 輸出: 命中檔案清單(去重、排序),一行一個路徑;exit 0 一律成功,即使沒有命中。
|
||||
set -eu
|
||||
# 掃描範圍: **只掃正本 marketplace 上的 domain 存取庫**。
|
||||
# 工作區可能還放著不屬於技能組的存取庫(例 shared、persona、code、doc)與
|
||||
# 點開頭的目錄(例 .jsc-monorepo-archive、.kiro),掃進去會讓刪除技能改到
|
||||
# 技能組以外的檔案。domain 清單取自 marketplace.json,不寫死。
|
||||
# 每個 domain 先找 {root}/{domain},再找 {root}/jsc-{domain};兩者都沒有就略過。
|
||||
# 每個存取庫內排除 .git 目錄。
|
||||
# 根目錄預設取本腳本位置的上兩層(meta/tools -> meta -> 根),換機器不必改腳本;
|
||||
# 用 JSC_PLUGINS_ROOT 覆寫,指向別處的技能組工作目錄。
|
||||
# 輸出: 命中檔案清單(去重、排序),一行一個路徑(stdout);掃描摘要走 stderr。
|
||||
# 結束碼: 0=有命中 1=掃完但零命中 2=用法錯誤
|
||||
# 3=找不到根目錄、讀不到 domain 清單、本機一個 domain 存取庫都沒有,或掃描失敗
|
||||
# 零命中與掃描失敗必須分開:拿掃描失敗當「沒有引用」會讓刪除技能少改檔案。
|
||||
set -u
|
||||
|
||||
usage() {
|
||||
echo 'usage: find-skill-refs.sh <domain> <skill-name>' >&2
|
||||
@@ -22,13 +35,51 @@ usage() {
|
||||
[ "$#" -eq 2 ] || usage
|
||||
DOMAIN=$1
|
||||
SKILL=$2
|
||||
[ -n "$DOMAIN" ] && [ -n "$SKILL" ] || usage
|
||||
|
||||
ROOT=/root/plugins
|
||||
[ -d "$ROOT" ] || { echo "找不到 plugins 根目錄: $ROOT" >&2; exit 1; }
|
||||
HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT="${JSC_PLUGINS_ROOT:-$(CDPATH= cd -- "$HERE/../.." && pwd)}"
|
||||
[ -d "$ROOT" ] || { echo "找不到 plugins 根目錄:$ROOT(可用 JSC_PLUGINS_ROOT 指定)" >&2; exit 3; }
|
||||
|
||||
# 正本 domain 清單:優先讀本機任一份 marketplace 副本(每個 repo 都帶同一份)。
|
||||
mkt=""
|
||||
for cand in "$HERE/../.claude-plugin/marketplace.json" "$ROOT"/*/.claude-plugin/marketplace.json; do
|
||||
[ -f "$cand" ] && { mkt="$cand"; break; }
|
||||
done
|
||||
[ -n "$mkt" ] || { echo "找不到 marketplace.json,無法判定 domain 清單" >&2; exit 3; }
|
||||
DOMAINS=$(sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"jsc-\([a-z0-9-]*\)".*/\1/p' "$mkt" | sort -u)
|
||||
[ -n "$DOMAINS" ] || { echo "marketplace.json 裡沒有 jsc-{domain} 條目:$mkt" >&2; exit 3; }
|
||||
|
||||
# 只收本機存在、且不是點開頭目錄的 domain 存取庫路徑。
|
||||
TARGETS=""
|
||||
for d in $DOMAINS; do
|
||||
for cand in "$ROOT/$d" "$ROOT/jsc-$d"; do
|
||||
[ -d "$cand" ] || continue
|
||||
TARGETS="$TARGETS $cand"
|
||||
break
|
||||
done
|
||||
done
|
||||
[ -n "$TARGETS" ] || { echo "本機找不到任何 domain 存取庫:$ROOT(先跑 sync-domains.sh)" >&2; exit 3; }
|
||||
|
||||
PATTERN1="$SKILL"
|
||||
PATTERN2="/jsc-${DOMAIN}:${SKILL}"
|
||||
|
||||
grep -rlE --exclude-dir=.git -e "$PATTERN1" -e "$PATTERN2" "$ROOT" 2>/dev/null | sort -u
|
||||
TMP=$(mktemp) || { echo "無法建立暫存檔" >&2; exit 3; }
|
||||
trap 'rm -f "$TMP"' EXIT
|
||||
# grep 的結束碼要單獨看:接管線的話 sort 永遠回 0,掃描失敗就被吃掉了。
|
||||
# shellcheck disable=SC2086
|
||||
grep -rlI --exclude-dir=.git -e "$PATTERN1" -e "$PATTERN2" $TARGETS > "$TMP" 2>/dev/null
|
||||
status=$?
|
||||
[ "$status" -le 1 ] || { echo "掃描失敗:$ROOT(grep 結束碼 $status)" >&2; exit 3; }
|
||||
OUT=$(sort -u "$TMP")
|
||||
|
||||
count=$(printf '%s' "$TARGETS" | wc -w | tr -d ' ')
|
||||
if [ -z "$OUT" ]; then
|
||||
echo "掃描完成,零命中:$count 個 domain 存取庫" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$OUT"
|
||||
printf '掃描完成,命中 %s 個檔案(掃了 %s 個 domain 存取庫;技能名稱為純子字串比對,請逐檔確認)\n' \
|
||||
"$(printf '%s\n' "$OUT" | wc -l | tr -d ' ')" "$count" >&2
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user