Skip to content

Plugin: manifesto, guardas de protocolo, subagentes por fase e distribuição - #43

Merged
CRangelP merged 7 commits into
mainfrom
feat/plugin
Aug 9, 2026
Merged

Plugin: manifesto, guardas de protocolo, subagentes por fase e distribuição#43
CRangelP merged 7 commits into
mainfrom
feat/plugin

Conversation

@CRangelP

@CRangelP CRangelP commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Transforma a skill em plugin de Claude Code, sem deixar de ser skill. Instalar
por cópia continua funcionando; o que muda é que agora ela também é
instalável, versionada, e capaz de trazer garantias que uma skill sozinha não
tem.

Por que

O repo já tinha crescido para além do formato skill: 5 mil linhas de bash, um
contrato de exit codes, três suítes e CI. Estava usando a pasta de skills como
se fosse um pacote.

E, mais importante: as regras mais críticas do protocolo — nunca
git reset --hard, nunca git clean, nunca push, nunca commit na main,
staging por pathspec — viviam como prosa que um modelo pode não seguir. Hooks
de plugin são a única forma de torná-las tão determinísticas quanto
rollback_test.sh já as trata.

O que entra

Manifesto (.claude-plugin/plugin.json). Com SKILL.md na raiz, a pasta
carrega como plugin de skill única; copiada para ~/.claude/skills/, carrega
como plugin de diretório de skills. Nada muda para quem já usa.

Gate por caminho absoluto. Instalado como plugin a pasta vive num
diretório de cache, e scripts/gate.sh seria lido como relativo ao projeto
sendo limpo — onde não existe. Agora é
"${CLAUDE_PLUGIN_ROOT:-.}/scripts/gate.sh", e o :-. mantém a instalação
por cópia intacta.

Os cinco guardas (hooks/hooks.jsonscripts/guard.sh). PreToolUse
com pré-filtro Bash(git *), bloqueando git reset --hard, git clean,
git push, git commit na main e staging de árvore inteira.

Duas decisões que só apareceram implementando:

  • Escopo. O guarda só acorda dentro de uma run: branch cleanup/, ou
    CLEANUP_PROGRESS.md não rastreado. O "não rastreado" não é detalhe —
    log rastreado numa branch normal é limpeza já mergeada, e sem essa distinção
    o guarda ficaria ativo na main para sempre depois do primeiro merge.
  • Falha aberta. Sem repo, JSON inválido, sem campo command: sai 0 e
    cala. A skill aborta o pipeline quando um comando do protocolo é
    bloqueado, então um falso positivo derruba uma run legítima.

Sai 0 ou 2, nunca 1: o contrato de hook lê 1 como erro não-fatal e deixa o
comando passar — seria o guarda falhando em silêncio. Invariante nas duas
suítes.

Cinco subagentes (agents/), um por fase, com survey e implementação
separados nas fases 2 e 3. Os dois de survey declaram
disallowedTools: Write, Edit: o checkpoint deixa de depender de boa vontade,
porque um survey que consegue escrever é um survey que consegue decidir.

Marketplace no próprio repo + CHANGELOG. A versão é semver explícita de
propósito: sem ela a chave de cache vira o SHA e todo push vira update. O
esquecimento de bump virou invariante, não disciplina.

Suítes: 3 → 4

scripts/guard_test.sh, 42 casos. A metade que mais importa é o que o guarda
deixa passar: rollback canônico, git add -- por pathspec, revert,
mv, stash push -u, e vizinhos como git cleanup-branch e
git add -Applies.

Invariantes de coerência: 151 → 248. Os novos ligam cada comando bloqueado à
tabela dos dois READMEs, cada agent ao Step 0.2, e o CHANGELOG ao manifesto.
Todos foram testados contra uma regressão simulada — invariante que passa por
construção não entrou.

How to verify

bash scripts/test.sh
/bin/bash scripts/test.sh   # bash 3.2 de fábrica do macOS
# esperado: 127/127 cases, 42/42 guard cases, 5/5 properties, 248/248 invariants

claude plugin validate . --strict
claude --plugin-dir . -p "liste as skills disponíveis"
# esperado: codebase-cleanup:codebase-cleanup

Validado também em container Linux (node:22-bookworm) e com o CLI real
(v2.1.220): plugin validate passa nos dois manifestos, os 5 agents carregam
namespaceados, e o ciclo marketplace add ./listremove completa.

O que fica de fora

Validar o plugin instalado numa limpeza real — #34. É o único teste que
nenhuma suíte alcança: o matcher entregando a chamada ao guarda, o
${CLAUDE_PLUGIN_ROOT} resolvendo do cache, o exit 2 chegando ao modelo como
bloqueio.

… de skill

Instalado como plugin, a pasta é copiada para um diretório de cache cujo
caminho ninguém adivinha, e um 'scripts/gate.sh' nu seria lido como relativo
ao projeto sendo limpo — onde ele não existe. O :-. mantém a instalação como
skill pura funcionando. Um invariante novo cobre as sete formas no protocolo;
os READMEs ficam de fora porque lá o caminho nomeia o arquivo, não um passo.
A skill proíbe reset --hard, clean, push, commit na main e staging de árvore
inteira — em prosa, que é conselho que um modelo pode perder. Instalada como
plugin ela passa a barrar os cinco no PreToolUse, antes de rodarem.

O guarda só acorda dentro de uma run (branch cleanup/, ou CLEANUP_PROGRESS.md
não rastreado) porque hooks de plugin disparam em toda sessão que o habilita,
e esses comandos são trabalho normal em qualquer outro lugar. Log rastreado é
limpeza mergeada, não run em curso: sem essa distinção o guarda ficaria ativo
na main para sempre depois do primeiro merge.

Falha aberta em tudo o que for ambíguo. A skill aborta o pipeline quando um
comando do protocolo é bloqueado, então um falso positivo derruba uma run
legítima — pior que guarda nenhum. Sai 0 ou 2 e nunca 1: o contrato de hook lê
1 como erro não-fatal e deixa o comando passar.

42 casos novos em guard_test.sh, a metade que importa sendo o que ele deixa
passar; e invariantes ligando cada comando bloqueado à tabela dos dois READMEs.
Antes a instalação era copiar uma pasta: sem versão, sem canal de atualização,
e uma correção de protocolo só chegava a quem copiasse de novo. O marketplace
mora no mesmo repo, então /plugin marketplace add aponta para o próprio
GitHub e /plugin update passa a existir.

A versão é explícita e semver de propósito. Sem ela a chave de cache vira o
SHA do commit e todo push vira update; com ela, o usuário só recebe o que foi
bumpado — e é por isso que o esquecimento de bump virou invariante, e não
disciplina.

Copiar a pasta continua funcionando e continua sendo skill; o que muda é de
onde vem a atualização. A invocação como plugin leva o namespace
(/codebase-cleanup:codebase-cleanup), e os dois READMEs dizem isso.
…vez de descrever

O Step 0.2 descrevia o contrato de delegação em prosa e deixava o
orquestrador remontá-lo a cada run. Agora são cinco agents em agents/: fases
1 e 1.5 num só, e um par survey/implementação para as fases 2 e 3.

A divisão survey/implementação é onde mora o checkpoint, e ela deixa de
depender de boa vontade: os dois agents de survey declaram
disallowedTools: Write, Edit, então a pergunta chega ao usuário antes de
qualquer mudança — um survey que consegue escrever é um survey que consegue
decidir, que é exatamente o que o checkpoint existe para impedir.

Nenhum deles declara hooks, mcpServers ou permissionMode: plugin agents não
suportam esses campos e o Claude Code recusa o agent inteiro. Virou
invariante em vez de descoberta na máquina de um usuário.

O invariante da árvore dos READMEs também aprendeu agents/: antes ele assumia
que todo .md listado morava em references/, e os cinco arquivos novos
apareceram como "references/cleanup-phase-2-impl.md não existe no disco".
Agora cobre os dois diretórios, nos dois sentidos.
A versão do plugin.json é a chave de cache que decide se uma instalação
enxerga atualização. Esquecer o bump falha em silêncio dos dois lados: ninguém
recebe erro, a correção só nunca chega. O CHANGELOG dá significado ao número,
e um invariante prova que os dois dizem a mesma coisa.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@CRangelP
CRangelP merged commit 3e5d6dc into main Aug 9, 2026
2 checks passed
@CRangelP
CRangelP deleted the feat/plugin branch August 9, 2026 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant