Verificação de ativação da skill
Uma skill só vale a pena se o modelo a alcançar no momento certo. Essa
decisão é tomada quase inteiramente a partir do description no frontmatter da skill — então
"minha skill é ativada?" é uma pergunta mensurável, e é assim que você a mede:
construa um conjunto rotulado de solicitações do usuário, execute um agente real em cada uma
e avalie se a skill foi engajada.
A solicitação do usuário é: $ARGUMENTS
Passo 1 — Localizar a skill alvo
$ARGUMENTS pode ser um caminho para um SKILL.md, um caminho para o diretório da skill, um
nome de skill, ou vazio.
- Vazio: faça glob em
.claude/skills/*/SKILL.mde**/skills/*/SKILL.md. Uma correspondência → use-a. Várias → liste-as e pergunte qual. Nenhuma → informe e pare. - Um diretório: use o
SKILL.mddentro dele. - Um nome: encontre o diretório da skill correspondente.
O nome simples da skill é o nome do diretório que contém SKILL.md. Leia o
description no frontmatter e mantenha-o à sua frente: essa string é com a qual o modelo
se compara, portanto é a entrada principal para o design das linhas e a coisa para a qual
você acabará recomendando edições.
Meça seu comprimento enquanto estiver lá — dois orçamentos separados o truncam, e qualquer um deles produz um resultado de baixo recall que parece exatamente com uma redação ruim.
- Truncamento por skill.
descriptionewhen_to_usesão concatenados e cortados em um orçamento fixo de caracteres — 1.536 caracteres, configurável através da configuraçãoskillListingMaxDescChars. O texto de ativação após o corte não pode afetar a ativação, então é como se não existisse. - O orçamento da listagem inteira, que importa mais exatamente nos repositórios que executam conjuntos de ativação. A listagem sempre contém o nome de cada skill, mas seu orçamento total de caracteres escala em cerca de 1% do contexto do modelo, compartilhado entre todas as skills que o usuário instalou. Quando transborda, o Claude Code descarta descrições começando pelas skills que você menos invoca.
O segundo tem uma consequência que vale a pena declarar claramente: em um repositório com muitas skills, uma skill pode ter recall quase zero com uma descrição perfeitamente boa, porque sua descrição nunca esteve na listagem. Reescrever a redação então não conserta nada. E a ordem de descarte é primeiro as menos invocadas, então uma skill recém-criada — que por definição é raramente invocada, e é exatamente o que alguém executa este conjunto — é a vítima mais provável. Isso é um viés sistemático contra a skill sob teste.
Alavancas, se o problema for a listagem: skillListingBudgetFraction (o padrão de 1%), a
variável de ambiente SLASH_COMMAND_TOOL_CHAR_BUDGET (uma contagem fixa de caracteres), e
skillOverrides definido como "name-only" para liberar orçamento de skills que você não
precisa que correspondam.
Se a skill não tiver description em seu frontmatter, pare e relate isso como a
constatação — uma skill sem descrição nunca pode ser invocada pelo modelo, então um conjunto
teria recall zero por construção e não te diria nada que você já não saiba.
Passo 2 — Confirmar que o coder-eval está instalado
Execute coder-eval --version. Instalar este plugin não instalou a CLI, e o
conjunto não pode ser validado ou executado sem ele.
Se estiver faltando, siga ${CLAUDE_PLUGIN_ROOT}/reference/cli-setup.md: ofereça a
instalação, pergunte antes de executá-la, e confirme com coder-eval --version
depois. Nunca instale sem solicitação e não continue se o usuário recusar.
Essa referência também cobre a outra metade da verificação de versão — se este projeto fixa uma versão do coder-eval, e o que fazer quando a versão instalada não corresponde a ela.
Passo 3 — Verificar o que já cobre esta skill
Antes de projetar qualquer coisa, veja o que o repositório já tem. Localize a árvore de tarefas
conforme ${CLAUDE_PLUGIN_ROOT}/reference/repo-layout.md e faça glob nela por uma tarefa que
contenha um critério skill_triggered.
Se um conjunto existente já nomeia esta skill, relate sua cobertura — quantas
linhas positivas e distratoras, quais suite_thresholds ela usa — e ofereça-se para
estendê-la anexando linhas ao seu conjunto de dados, em vez de criar um conjunto
e paralelo. Dois conjuntos para uma skill divergem e o usuário paga por ambos em cada
execução. Crie um novo apenas quando nada cobrir esta skill, ou quando o usuário escolher
fazê-lo depois de ver o que existe.
Duas coisas que vale a pena relatar em vez de contornar silenciosamente:
- Um conjunto existente sem linhas distratoras. A precisão é 1,0 por definição, então metade do resultado não tem significado. Ofereça-se para adicionar distratores — uma melhoria real tanto em relação a criar um conjunto rival quanto a não dizer nada.
- Um conjunto vizinho que nomeia uma skill diferente. Isso não é cobertura. Siga em frente e crie, e diga por que o vizinho não contou.
Em seguida, verifique de onde agent.plugins deve vir. Se um experimento contra o qual a
tarefa será resolvida já fornece esse bloco, herde-o e não escreva um novo — uma tarefa
que redeclara o que o experimento fornece diverge dele, sem nada para detectar a divergência.
Escreva o próprio bloco do modelo apenas quando nada já expuser a skill para a
sandbox. Se existirem vários experimentos e não estiver claro contra qual esta tarefa será
resolvida, pergunte em vez de adivinhar.
Passo 4 — Projetar as linhas
Este passo é todo o experimento. O resto é mecânica.
Linhas positivas — solicitações que um usuário real faria de forma plausível e que a descrição afirma cobrir. Parafraseie; nunca copie frases da descrição. Uma linha extraída da descrição testa correspondência de string, não ativação. Varie o vocabulário e inclua pelo menos uma linha oblíqua onde o usuário descreve seu problema em vez da operação que a skill realiza.
Linhas distratoras — solicitações adjacentes que a skill não deve reivindicar, especialmente aquelas que compartilham vocabulário com a descrição. São essas que tornam a precisão significativa.
Linhas de skill irmã (opcional) — solicitações que pertencem legitimamente a uma skill
nomeada diferente no mesmo repositório, com expected_skill definido para essa
skill irmã. Em um repositório com várias skills, o desvio entre duas skills adjacentes é a
falha comum, e um distrator simples mostra apenas que um erro ocorreu, não para onde
ele foi. Essas linhas dizem para onde.
Adicione-as quando duas skills tiverem sobreposição de assunto e você quiser saber qual vence. Elas custam linhas extras, e cada linha é uma execução completa do agente — então trate-as como um acompanhamento direcionado, não um padrão.
Nunca nomeie a skill em um prompt. Isso testa obediência, não ativação:
- Ruim: "Use a skill pdf-forms para preencher esta aplicação."
- Bom: "Preciso preencher os campos deste PDF de aplicação e enviá-lo de volta."
Esta regra não é afetada por linhas de skill irmã: expected_skill é um rótulo no
conjunto de dados, lido pelo critério e nunca mostrado ao agente. O prompt da linha ainda
não deve nomear nenhuma skill, nem a irmã.
Dimensionamento. Mínimo de 3 positivas + 3 distratoras. Mire em 8–12 de cada para um sinal no qual você possa agir — recall com 3 linhas se move em saltos de 33 pontos, que é grosseiro demais para distinguir uma regressão real de ruído. O modelo enviado contém 6 linhas porque esse é o mínimo ilustrativo, não uma meta. Quaisquer linhas de skill irmã são por cima disso: 8–12 positivas mais 8–12 distratoras já são 16–24 execuções, então informe o total resultante antes de escrever o conjunto.
Recuse-se a gerar um conjunto sem linhas distratoras. Sem negativas, a precisão é 1,0 por definição e metade do resultado é sem significado. Diga o porquê e peça os casos adjacentes em vez disso.
Passo 5 — Escrever o conjunto
Copie os dois arquivos de modelo para a árvore de tarefas do usuário, localizada seguindo
${CLAUDE_PLUGIN_ROOT}/reference/repo-layout.md (se o repositório não tiver nenhuma, proponha um
local e pergunte):
${CLAUDE_PLUGIN_ROOT}/reference/templates/activation.yaml${CLAUDE_PLUGIN_ROOT}/reference/templates/activation-rows.jsonl
Em seguida, substitua, mantendo o JSONL ao lado do YAML (as entradas dataset.paths são
resolvidas relativas ao arquivo de tarefa):
task_id→<nome-da-skill>-activationskill_name→ o nome simples da skill- O
expected_skillde cada linha positiva → o mesmo nome simples; linhas distratoras mantêm""; oexpected_skillde uma linha de skill irmã → o nome simples dessa skill irmã - O
promptde cada linha → as solicitações projetadas no passo 4, um objeto JSON por linha
Em seguida, torne a skill acessível, que é o passo que decide se o conjunto mede algo.
A tarefa é executada em uma sandbox nova que não contém nenhum dos arquivos do usuário, então o
agente não recebe nenhuma skill a menos que a tarefa diga onde elas estão. Esse é o bloco
agent.plugins no modelo — e é trabalho do modelo apenas quando nada já expõe a
skill: se o passo 3 encontrou um experimento fornecendo esse bloco, herde-o e exclua a
cópia do modelo em vez de escrever uma segunda declaração.
Caso contrário, preencha-o. path deve ser uma raiz de plugin: um diretório que contém um
subdiretório skills/, para que a skill fique em <path>/skills/<nome-da-skill>/SKILL.md. Um
.claude-plugin/plugin.json é opcional — sem ele, o namespace assume o padrão do próprio nome do
diretório.
Para .claude/skills/pdf-forms/SKILL.md, essa raiz é .claude, não .claude/skills.
Apontar para um diretório simples de diretórios de skill não carrega nada.
Prepare uma raiz mínima em vez de apontar para o próprio .claude. Uma raiz de plugin carrega
o plugin INTEIRO, não apenas suas skills: um diretório agents/, commands/ ou hooks/ ao lado
de skills/ se torna visível para o agente avaliado também. Aponte para o .claude de um
repositório e você entrega ao agente todo subagente e comando do projeto — e um subagente que
pode responder à solicitação é um fator de confusão, não um detalhe. Se .claude/agents/pdf-expert.md
existir enquanto você mede pdf-forms, o agente pode delegar a ele em vez de chamar a skill;
skill_triggered registra no, e o recall cai por um motivo que não tem nada a ver com a
descrição da skill. Também torna o número dependente do repositório, então dois conjuntos não
são mais comparáveis.
Portanto, construa uma raiz que contenha exatamente a unidade sob teste e aponte para ela:
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"
Use cp -R em vez de ln -s onde links simbólicos são complicados (Windows, algumas imagens de CI). Se
o usuário preferir a linha única, export SKILL_SOURCE_PATH="$(pwd)/.claude" ainda funciona —
diga claramente que também expõe todo o resto sob .claude, então um baixo recall pode ser
dos irmãos em vez da skill.
Mantenha-o como uma variável de ambiente em vez de fixar um caminho absoluto no YAML — o conjunto é commitado e reexecutado em outras máquinas. Se a variável não estiver definida, a skill está simplesmente ausente, toda linha positiva pontua 0, e o resultado é indistinguível de uma skill que nunca dispara, então confirme que está definida antes de relatar qualquer constatação de baixo recall.
skill_name deve ser o nome simples mesmo quando a skill vem de um plugin e é
invocada como plugin:skill — o verificador remove o namespace antes de comparar. Um
valor com namespace aqui silenciosamente pontua zero recall em toda linha, o que se lê exatamente
como uma skill quebrada.
Como a correspondência é por nome simples, ela não pode sobreviver a uma colisão de nomes. Duas skills
chamadas init — uma de um plugin, outra nativa — são a mesma string para o critério, então ele
creditará qualquer uma que disparar como se fosse a que está sob teste. Verifique se o nome é único em
tudo o que está instalado antes de confiar em um resultado (/context e /doctor listam o conjunto
ativo). Uma colisão não gera erro; ela mede a skill errada. Se existir uma, diga isso em vez de
relatar o número — renomear a skill, ou medir onde a colisão está ausente, são as únicas
alterações honestas.
Para campos de critério além deste modelo, leia
${CLAUDE_PLUGIN_ROOT}/reference/criteria.md.
Passo 6 — Validar antes de gastar qualquer coisa
coder-eval plan <caminho-para-activation.yaml> deve sair com 0. É apenas uma verificação de
esquema — não lê o arquivo de conjunto de dados — então também confirme que o JSONL está ao lado
do YAML e tem um objeto por linha.
Passo 7 — Executar
Cada linha é uma execução completa do agente: N linhas significa N execuções e custo real de tokens. Informe a contagem de linhas e o agente/modelo que será usado, e então pergunte antes de iniciar.
coder-eval run <caminho-para-activation.yaml>
O critério é agnóstico em relação ao agente — ele detecta o Claude engajando a skill através da
ferramenta Skill, e qualquer agente sem essa ferramenta (Codex, por exemplo) lendo os arquivos da
skill do disco — então o mesmo conjunto funciona independentemente do agente para o qual a tarefa for
resolvida.
Passo 8 — Relatar e interpretar
Apresente recall, precisão, F1 e a matriz de confusão, e então diga o que significam:
- Baixo recall (perde linhas que deveria ter capturado): descarte truncamento e evicção de
listagem antes de concluir que a descrição subestima. Ambos produzem um resultado de baixo
recall indistinguível de má redação, e ambos são baratos de verificar:
/doctorestima o custo de contexto da listagem e seus maiores contribuintes, e a linha Skills em/contextrelata o tamanho da listagem após a aplicação do orçamento — isso é o que o modelo realmente recebeu. Somente quando a descrição estiver demonstravelmente na listagem e dentro do corte por skill é que a redação é a culpada: ela não nomeia as situações, tipos de arquivo ou frases que deveriam ativá-la. - Baixa precisão (dispara em distratores): a descrição superestima e está roubando solicitações adjacentes. Estreite-a e diga explicitamente para que a skill não serve.
- Erros concentrados em um irmão (com linhas de skill irmã): isso é uma disputa de fronteira entre duas descrições, não uma descrição vaga. Consertar a skill sob teste isoladamente tende a mover a falha em vez de removê-la — diga explicitamente para que cada uma das duas skills não serve e reexecute.
- Ambos altos: relate os números e a contagem de linhas, e observe que um conjunto pequeno diz pouco — ofereça-se para ampliá-lo.
Aponte para o description no frontmatter como a coisa a editar, cite as linhas específicas
que falharam e encerre com uma pergunta: "Devo modificar a descrição e executar novamente o
conjunto?"