Communitygithub.com

UiPath/check-skill

生成並執行一個 coder-eval 激活測試套件,用於驗證 Claude Code 技能是否會正確觸發。當使用者詢問某個技能是否會觸發、想測試技能啟動、或擔心某技能已無聲無息停止運作時使用。

check-skill 是什麼?

此技能旨在系統化評估與驗證 AI 代理(特別是 Claude Code)中的技能是否能在正確時機被模型喚起。它能建立一組標記好的使用者請求,針對每個請求運行真實代理,並判定技能是否被啟用。這對於診斷技能觸發失敗原因(如前端描述不足、技能清單截斷、命名衝突等)至關重要。支援多種平台(Claude Code、Codex 等),並提供可操作的建議來修正觸發問題。主要功能包括:定位待測技能、檢查技能描述是否被截斷或從清單中剔除、設計正例與干擾測試用例、生成測試套件、並在報告中解釋召回率、精確率與 F1 分數。

相容平台✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/UiPath/coder_eval/tree/main/plugins/coder-eval/skills/check-skill

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

技能激活檢查

技能只有當模型在正確時機主動使用它時才有價值。而這個決定幾乎完全取決於技能前端 YAML 中的 description 欄位——因此「我的技能會觸發嗎?」是一個可衡量的問題,而以下是衡量方法:建立一組標記好的使用者請求,針對每個請求運行真實代理,並評分技能是否被啟用。

使用者的請求是:$ARGUMENTS

步驟 1 — 定位目標技能

$ARGUMENTS 可以是一個 SKILL.md 的路徑、該技能目錄的路徑、技能名稱,或為空。

  • 空:使用 glob 模式搜尋 .claude/skills/*/SKILL.md 和 **/skills/*/SKILL.md。找到一個相符項目→使用它。找到多個→列出它們並詢問是哪一個。沒有找到→說明情況並停止。
  • 目錄:使用該目錄內的 SKILL.md。
  • 名稱:尋找相符的技能目錄。

技能的裸名稱就是包含 SKILL.md 的目錄名稱。讀取前端的 description 並記住它:這個字串是模型比對的依據,因此它是行設計的主要輸入,也是你最終會建議修改的對象。

在處理的同時測量其長度——有兩個獨立的預算會對齊進行截斷,其中任何一個都會產生看起來完全像措辭不良的低召回結果。

  1. 每個技能的截斷。 description 和 when_to_use 會被串接起來,並在固定的字元預算處截斷——1,536 個字元,可透過 skillListingMaxDescChars 設定進行配置。超出此限制的觸發文字完全無法影響激活,因此它們等同於不存在。
  2. 整個清單的預算,這在那些會運行激活套件的儲存庫中更為重要。 清單總是包含每個技能的名稱,但其總字元預算大約為模型上下文視窗的 1%,由使用者安裝的每個技能共享。當它溢出時,Claude Code 會從你最少使用的技能開始刪除描述。

第二點有一個值得直白說明的後果:在一個具有多個技能的儲存庫中,一個技能即使有完全良好的描述也可能獲得接近零的召回率,因為它的描述根本從未出現在清單中。之後重寫措辭也無法解決任何問題。而且刪除順序是最少使用的最先被刪,因此一個新創建的技能——定義上即很少被調用,且正是有人會對此運行此套件的對象——是最有可能的受害者。這是一個針對被測試技能的系統性偏差。

如果問題出在清單上,可以調整的槓桿有:skillListingBudgetFraction(預設為 1%)、SLASH_COMMAND_TOOL_CHAR_BUDGET 環境變數(一個固定的字元數),以及將 skillOverrides 設定為 "name-only" 以釋放那些你不需要比對的技能的預算。

如果技能在其前端沒有 description,則停止並報告此發現——一個沒有描述的技能永遠不可能被模型喚起,因此測試套件建構上就會得到零召回率,而這並不能告訴你任何你還不知道的事。

步驟 2 — 確認 coder-eval 已安裝

運行 coder-eval --version。安裝此插件並不會安裝 CLI,而沒有它則無法驗證或運行測試套件。

如果它缺失,請遵循 ${CLAUDE_PLUGIN_ROOT}/reference/cli-setup.md:提供安裝選項,在運行前先詢問,並在之後用 coder-eval --version 確認。切勿未經提示就安裝,且如果使用者拒絕則不要繼續。

那份參考文件也涵蓋了版本檢查的另一半——此專案是否鎖定了某個 coder-eval 版本,以及當已安裝的版本與之不符時該怎麼做。

步驟 3 — 檢查哪些內容已經涵蓋此技能

在設計任何東西之前,先查看儲存庫中已有的內容。根據 ${CLAUDE_PLUGIN_ROOT}/reference/repo-layout.md 找到任務樹,並對其進行 glob 搜尋,尋找帶有 skill_triggered 標準的任務。

如果已有測試套件指名了此技能,則報告其覆蓋範圍——有多少正例和干擾行,它設定的 suite_thresholds 是什麼——並提議擴展它,透過將行附加到其資料集中,而不是建立一個平行的測試套件。針對一個技能建立兩個測試套件會使它們產生分歧,而使用者每次運行時都需為兩者付費。只有當沒有任何東西涵蓋此技能時,或者當使用者在看到現有內容後選擇這樣做時,才建立新的測試套件。

有兩件事值得報告,而不是默默地繞道解決:

  • 一個沒有干擾行的現有測試套件。 精確率定義上為 1.0,因此其結果的一半是無意義的。提議添加干擾項——這比建立一個競爭的測試套件或什麼都不說,是更實際的改進。
  • 一個指名了不同技能的相鄰測試套件。 這不算覆蓋。繼續建立新的測試套件,並說明為什麼相鄰的套件不算數。

然後檢查 agent.plugins 應該來自哪裡。 如果任務所要解析的實驗已經提供了該區塊,則繼承它且不要另行撰寫——一個重新宣告實驗已提供內容的任務會與實驗產生分歧,且沒有任何機制能捕捉到這個差異。只有在沒有東西能將該技能暴露給沙箱時,才撰寫模板自己的區塊。如果存在多個實驗且不清楚此任務要解析哪一個,請詢問而不是猜測。

步驟 4 — 設計測試行

這一步是整個實驗的核心。其餘的都是機械性操作。

正例行——真實使用者可能合理提出的、且描述聲稱能涵蓋的請求。進行改寫;切勿從描述中複製措辭。直接從描述中擷取的行測試的是字串比對,而非激活。變化詞彙,並至少包含一個間接的行,其中使用者描述他們的問題而不是技能執行的操作。

干擾行——技能不應該回應的相鄰請求,尤其是那些與描述共享詞彙的請求。這些是使精確率有意義的關鍵。

同屬其他技能的行 (可選)——那些合法屬於同一儲存庫中已命名的其他技能的請求,並將其 expected_skill 設為該同屬技能。在一個多技能的儲存庫中,兩個相鄰技能之間的錯誤路由是常見的故障,而一個普通的干擾行只能顯示發生了誤觸,卻無法顯示誤觸到哪裡去了。這些行能指出位置。

當兩個技能的主題領域重疊,且你想知道哪個技能會勝出時,可添加它們。它們會增加行數,而每一行都是一次完整的代理運行——因此應將其視為有針對性的後續行動,而非預設選項。

切勿在提示中提及技能名稱。 這測試的是服從性,而非激活:

  • 糟糕:「使用 pdf-forms 技能填寫此申請表。」
  • 良好:「我需要填寫這份 PDF 申請表上的欄位並將其寄回。」

此規則不受同屬其他技能的行影響:expected_skill 是資料集中的一個標籤,由標準讀取,且絕不會顯示給代理。該行的 prompt 仍然不得提及任何技能名稱,包括同屬技能。

規模設定。 至少 3 個正例 + 3 個干擾。目標是每種 8-12 個,以獲得可據以行動的信號——基於 3 行的召回率以 33 個百分點為單位跳動,這過於粗糙,無法區分真正的回歸與雜訊。提供的模板包含 6 行,因為這是最低說明性數量,而非目標。任何同屬其他技能的行都是在此之上的:8-12 個正例加上 8-12 個干擾已經達到 16-24 次運行,因此在撰寫測試套件前應說明最終總數。

拒絕生成沒有干擾行的測試套件。 沒有負例,精確率定義上為 1.0,結果的一半是無意義的。說明原因並要求提供相鄰案例。

步驟 5 — 撰寫測試套件

將兩個模板檔案複製到使用者的任務樹中,其位置由 ${CLAUDE_PLUGIN_ROOT}/reference/repo-layout.md 決定(如果儲存庫沒有,則建議一個位置並詢問):

  • ${CLAUDE_PLUGIN_ROOT}/reference/templates/activation.yaml
  • ${CLAUDE_PLUGIN_ROOT}/reference/templates/activation-rows.jsonl

然後進行替換,保持 JSONL 檔案與 YAML 檔案相鄰(dataset.paths 條目是相對於任務檔案解析的):

  • task_id → <技能名稱>-activation
  • skill_name → 裸的技能名稱
  • 每個正例行的 expected_skill → 相同的裸名稱;干擾行保持為 "";同屬其他技能行的 expected_skill → 該同屬技能的裸名稱
  • 每一行的 prompt → 在步驟 4 中設計的請求,每行一個 JSON 物件

然後使技能可被存取,這是決定測試套件是否真的在衡量東西的步驟。 任務在一個全新的沙箱中運行,其中不包含使用者的任何檔案,因此除非任務指定了技能的位置,否則代理不會獲得任何技能。這就是模板中 agent.plugins 區塊的作用——並且只有在沒有東西已經暴露該技能時,模板才需要負責此區塊:如果步驟 3 找到了一個提供該區塊的實驗,則繼承它並刪除模板的副本,而不是撰寫第二個宣告。

否則,填入它。path 必須是一個插件根目錄:一個包含 skills/ 子目錄的目錄,這樣技能就位於 <path>/skills/<技能名稱>/SKILL.md。.claude-plugin/plugin.json 是可選的——如果沒有,則命名空間預設為目錄本身的名稱。

對於 .claude/skills/pdf-forms/SKILL.md,其根目錄是 .claude,而不是 .claude/skills。指向一個純粹的技能目錄目錄無法載入任何東西。

建立一個最小的根目錄,而不是直接指向 .claude 本身。 一個插件根目錄會載入整個插件,而不僅僅是其技能:skills/ 旁的 agents/、commands/ 或 hooks/ 目錄也會對被評估的代理可見。指向一個儲存庫的 .claude 就等於把每個專案子代理和指令都交給了代理——而一個能夠回答請求的子代理是一個混淆因素,不是一個細節。如果 .claude/agents/pdf-expert.md 在你測試 pdf-forms 時存在,代理可能會將請求委派給它而不是呼叫該技能;skill_triggered 會記錄 no,而召回率會因一個與技能描述完全無關的原因而下降。這也使得數值依賴於特定的儲存庫,因此兩個測試套件不再具有可比性。

因此,建立一個僅包含待測單元的根目錄,並指向它:

SKILL_ROOT="$(mktemp -d)"
mkdir -p "$SKILL_ROOT/skills"
ln -s "$(pwd)/.claude/skills/pdf-forms" "$SKILL_ROOT/skills/pdf-forms"
export SKILL_SOURCE_PATH="$SKILL_ROOT"

在符號連結不方便的地方(Windows、某些 CI 映像),使用 cp -R 代替 ln -s。如果使用者偏愛一行指令,export SKILL_SOURCE_PATH="$(pwd)/.claude" 仍然有效——但要直白說明這也會暴露 .claude 下的所有其他東西,因此低召回率可能是同屬技能造成的,而非技能本身的問題。

將其保留為環境變數,而不是將絕對路徑寫死進 YAML 中——測試套件會提交並在其他機器上重新運行。如果該變數未設定,技能就會完全缺席,每個正例行都會得到 0 分,其結果與一個從不觸發的技能無法區分,因此在報告任何低召回率的發現之前,務必確認它已設定。

skill_name 必須是裸名稱,即使技能來自插件並以 plugin:skill 的形式被調用——檢查器會在比較前剝離命名空間。在這裡使用帶命名空間的值會導致每一行都默默地得到零召回率,這看起來就像一個壞掉的技能。

因為比對是基於裸名稱,所以它無法應對名稱衝突。 兩個名為 init 的技能——一個來自插件,一個是內建的——對標準來說是相同的字串,因此它會將任何觸發的技能都視為被測試的技能。在信任結果之前,請檢查該名稱在所有已安裝項目中是唯一的(/context 和 /doctor 會列出活躍集合)。名稱衝突不會報錯;它會測量到錯誤的技能。如果存在衝突,請說明情況而不是回報數字——重新命名技能,或在沒有衝突的環境中進行測量,才是唯一誠實的修正方法。

對於此模板以外的標準欄位,請閱讀 ${CLAUDE_PLUGIN_ROOT}/reference/criteria.md。

步驟 6 — 在花費任何資源之前進行驗證

coder-eval plan <路徑到-activation.yaml> 必須以退出碼 0 結束。它只是一個模式檢查——它不會讀取資料集檔案——因此也要確認 JSONL 檔案與 YAML 檔案相鄰,並且每行一個物件。

步驟 7 — 運行

每一行都是一次完整的代理運行:N 行代表 N 次運行和真實的 token 成本。說明行數以及將要使用的代理/模型,然後在開始前詢問。

coder-eval run <路徑到-activation.yaml>

此標準是代理無關的——它可以透過 Skill 工具檢測到 Claude 使用了技能,而對於任何沒有該工具的代理(例如 Codex),則透過從磁碟讀取技能的檔案來檢測——因此無論任務解析到哪個代理,同一個測試套件都能運作。

步驟 8 — 報告與解讀

呈現召回率、精確率、F1 分數以及混淆矩陣,然後說明它們的含義:

  • 低召回率(錯過了本應捕獲的行):在斷定描述涵蓋不足之前,先排除截斷和清單剔除的問題。 這兩者都會產生與措辭不良無法區分的低召回率結果,並且兩者都很容易檢查:/doctor 會估計清單的上下文成本及其最大貢獻者,而 /context 中的 Skills 行則會報告預算應用之後的清單大小——這才是模型實際收到的內容。只有在確認描述確實存在於清單中且在每個技能的截斷限制內時,措辭才是罪魁禍首:它沒有提到應該觸發該技能的情境、檔案類型或表述方式。
  • 低精確率(對於干擾項也觸發):描述過度承諾,正在搶奪相鄰的請求。縮小它的範圍,並明確說明這個技能不適用於什麼。
  • 誤觸集中於一個同屬技能(使用同屬其他技能的行時):這是兩個描述之間的邊界爭議,而不是一個模糊的描述。僅修復被測試的技能通常只會轉移故障,而不是消除它——明確說明這兩個技能各自的不適用範圍,然後重新運行。
  • 兩者都高:報告數值和行數,並指出一個小的測試套件說明不了什麼——提議擴大它。

將前端 description 指向為需要編輯的對象,引用導致結果的特定行,並提出具體的措辭建議。

與 /doctor 協作

/doctor 中的技能清單診斷是對此套件的補充,而不是替代。直接告知使用者:「結果取決於你的設定——如果不確定,我可以運行 /doctor 來檢查技能清單的健康狀況。」 最佳的工作流程是:

  1. 先執行 /doctor 以排除清單層面的問題。
  2. 只有在 /doctor 顯示描述確實出現在模型所見的內容中時,才執行此測試套件。
  3. 如果 /doctor 顯示描述被剔除,則在運行測試套件之前先調整設定(增加預算、禁用最少使用的技能等)。

Individual skills in this repo

This repo contains 5 individual skills — each has its own dedicated page.

相關技能