Método Expx
O método, escrito e executável
Pedir a um agente de IA para construir uma feature funciona — até a segunda hora. O plano era vago
o bastante para o agente decidir sozinho no meio da implementação, e ele decide: escolhe um padrão
que não é o do projeto, escreve o teste na pasta que o runner não olha, refatora três arquivos que
ninguém pediu. O método Expx é o conjunto das restrições que evitam isso, escrito. Este site é a
referência completa do expxdev — o CLI que instala e mantém as oito skills — e de cada
uma delas.
npx expxdev init
Apresentação para o time → — deck navegável em HTML, pronto para levar essa introdução a uma reunião de engenharia.
As quatro apostas
O método parte de quatro premissas, e tudo o mais decorre delas.
Todo o esforço vai para o planejamento
Uma pergunta feita durante a execução é sempre uma falha da fase de planejamento. Se a ambiguidade foi eliminada antes, a execução pode ser autônoma sem virar aposta.
Nada avança sem critério verificável
Task, fase e sprint têm portão de aceite binário, sem adjetivo. TDD não é sugestão: o teste vem antes, e a task só fecha com a suíte inteira verde.
O escopo é travado no que a investigação provou
O que não está no plano não é tocado. Melhoria avulsa vira registro de dívida, nunca um brinde no diff.
Quem implementa não aprova
O QA e a auditoria são papéis distintos, e os agentes que os executam têm acesso somente de leitura — o que transforma “aponta, não corrige” de promessa em impossibilidade técnica.
O método de ponta a ponta
Build e Run são a mesma disciplina
sprintx e runx não são dois métodos: são o mesmo método com gatilhos diferentes.
| sprintx (Build) | runx (Run) | |
|---|---|---|
| Gatilho | feature nova, planejada do zero | ocorrência num sistema em produção |
| Entrada | uma ideia, um requisito | um chamado, ticket ou relato de cliente |
| Estágios | F1…F6 | E1…E5 |
| Saída | a feature entregue | a ocorrência encerrada, com dois relatórios |
| Raiz em disco | docs/sprintx/features/<slug>/ | docs/manutencao/<OC-ID>-<slug>/ |
As duas compartilham exatamente os mesmos contratos: base de conhecimento antes de qualquer plano, hierarquia sprint → fase → task, TDD obrigatório com no mínimo dois testes por task, critério de aceite verificável em toda transição e execução autônoma guiada por um arquivo orquestrador. Muda o gatilho e o tamanho. Nunca o rigor.
Começar
Instalação
O init busca as skills que você escolher nos repositórios oficiais, empacota
apenas as selecionadas como um plugin local chamado expx e configura o harness.
Requisito: Node ≥ 20.19.0 e o git do sistema no PATH.
O CLI usa git clone --depth 1 justamente para aproveitar a credencial já configurada na
máquina — repositório privado funciona sem nenhum token.
O caminho declarativo
A seleção é feita por flag, o que faz a mesma linha servir ao seu terminal e ao CI:
npx expxdev init --skills sprintx,runx,mergex --harness claude,opencode --yes
| Flag | Efeito |
|---|---|
--skills <lista> | Skills a instalar, separadas por vírgula. Repetível; nomes duplicados são ignorados |
--harness <lista> | claude, opencode, ou os dois. Padrão: claude |
--yes · --sim | Aplica sem exigir terminal interativo |
Todas aceitam também a forma --flag=valor.
Sem terminal interativo e sem --yes, o init imprime o
que instalaria e sai sem escrever nada. É o modo de simulação, e é o que protege um CI de escrever por engano.
O caminho interativo
Rodando npx expxdev init sem --skills num terminal completo (stdin e stdout
precisam ser TTY), o CLI abre um assistente:
███████ ██ ██ ██████ ██ ██ dev
o CLI do metodo Expx · v0.5.0
? Quais skills instalar? (espaço marca, enter confirma)
◉ sprintx planeja e executa features novas
◉ runx ocorrencias de manutencao do dia a dia
◯ legadox camada para projetos legados
◯ stackx descobre o dialeto tecnico do repositorio
◉ mergex versionamento, entrega e revisao de pull requests
◯ memox memoria do projeto, indexa os artefatos ja fechados
◯ prodx camada de produto, decide se o pedido vira trabalho
? Qual harness? ◉ claude ◯ opencode
Resumo
skills sprintx, runx, mergex
harness claude
? Confirmar? (S/n)
Se já existe um .expx/ no projeto, o assistente pergunta antes se você quer reconfigurar,
com o padrão em não — seguir remonta a instalação a partir da nova seleção.
O que fica no seu projeto
rename ao final. Se falhar no meio, o .expx/ anterior é devolvido ao lugar.Sobre o registro do plugin. Declarar o marketplace na configuração do projeto
não instala o plugin — isso foi verificado em execução, não presumido da documentação. O init
chama claude plugin marketplace add e claude plugin install. Como esse registro
grava um caminho absoluto na configuração do usuário, ele não viaja no commit: cada pessoa roda
expx init na própria máquina. Sem o binário claude no PATH, o
.expx/ é montado normalmente e o CLI imprime os dois comandos para você rodar à mão.
Commite o .expx/
A instalação é travada por lock, e o lock é para ser versionado. Quem clona o projeto recebe exatamente
as mesmas skills que o time está usando, sem rede e sem rodar nada. O doctor trata como
erro um .gitignore que ignore o .expx/.
Próximo passo, dentro do Claude Code: /expx:onboarding. Ele mapeia
as camadas instaladas antes do primeiro plano — ver /expx:onboarding.
Começar
O ecossistema
Oito skills que não se conhecem por código: elas se encontram em contratos escritos. É isso que permite instalar três delas e não as outras cinco, ou atualizar uma sem tocar nas demais.
buildx é a única que exige companhia: sem prodx, sprintx e
mergex ela não tem o que orquestrar.As oito skills
Planeja e executa features novas em seis fases. Construir algo que não existe.
Ocorrências de manutenção em produção, em cinco estágios. Corrigir o que já está no ar.
Branch, commit por task, portão de prontidão, PR e pacote de QA. Levar o trabalho até o merge.
Endurece o trabalho em projeto legado, proporcional ao raio de impacto.
Descobre o dialeto técnico do repositório para o código novo parecer com o que já existe.
Indexa os artefatos fechados e responde o que já se sabe sobre um arquivo.
Recebe o pedido cru e emite um veredito com evidência. Decide se vale fazer.
Conduz um projeto inteiro, da descrição ao sistema pronto. Chama as outras na ordem certa.
Camadas sozinhas não fazem nada. legadox, stackx,
memox e prodx modificam o comportamento de sprintx e runx
em vez de agir por conta própria. O CLI avisa se você selecionar uma camada sem base, mas nunca impede.
A buildx é o caso oposto e a única exceção do método: ela não modifica ninguém — invoca.
Sem prodx, sprintx e mergex instaladas ela não roda, e diz o que falta.
É a única peça com dependência dura, porque rodar sem elas significaria reimplementar quatro skills mal,
dentro de uma quinta.
Como as camadas compõem
A prodx é a única que roda antes das outras: ela decide se existe
trabalho; as demais tratam de como fazê-lo. Sem ela, o método planeja com rigor uma feature que
não deveria existir — o desperdício mais caro de uma software house, porque passa em todos os testes.
| Quando a camada existe | O que muda na sprintx | O que muda na runx |
|---|---|---|
docs/stack/CONVENCOES.mdstackx |
a ingestão lê as convenções; a descoberta transforma cada PROPOSTA em pergunta; o plano define caminho do teste, camada e padrão de erro por task; a auditoria roda a verificação de aderência |
a investigação consulta o cartucho conforme o sintoma; o fix obedece o padrão de teste e o isolamento de banco |
docs/legado/PERFIL.mdlegadox |
cada fase ganha rigor proporcional ao raio: caracterização antes de alterar, orçamento de diff por task, plano de reversão, aprovação humana em raio ALTO |
|
mergex instalada |
abre a branch no início da F6, commita cada task, e entrega ao fim | abre a branch no início do E3, e entrega entre o E4 e o E5 |
docs/produto/ com veredito assinadoprodx |
a F1 recebe o BRIEFING.md como entrada, e o plano referencia o PD-ID de origem |
o BRIEFING.md vira o 00-OCORRENCIA.md, com o tipo já classificado |
A ausência nunca quebra. Sem CONVENCOES.md, sem PERFIL.md,
sem a mergex ou sem a prodx, as outras skills se comportam exatamente como se
comportariam sem elas. Insumo que não existe vira aviso do que falta — nunca invenção, e nunca um erro
que trava o trabalho.
A regra de precedência que evita o pior colateral
stackx descreve o que deve ser seguido daqui pra frente. legadox
descreve o que existe hoje, incluindo os dialetos conflitantes. Em projeto novo, só o
stackx governa. Em projeto legado, na área tocada manda o padrão local descrito no
PERFIL.md; o stackx governa apenas código novo, em arquivo novo.
Sem essa regra, a IA “moderniza” arquivo antigo achando que está obedecendo convenção — o colateral mais perigoso que existe, porque vem com a justificativa de estar seguindo uma regra.
Quadro comparativo
| Skill | Fases | Comandos | Agentes | Hooks | Raiz dos artefatos |
|---|---|---|---|---|---|
sprintx | 6 +F3.5 | 8 | 3 | 6 | docs/sprintx/ |
runx | 5 | 6 | 3 | 6 | docs/manutencao/ · docs/relatorios/ |
legadox | 11 | 6 | 2 | 7 | docs/legado/ |
stackx | 5 | 5 | 1 | 2 | docs/stack/ |
mergex | 10 | 7 | 2 | 6 | docs/entregas/ |
memox | 5 | 5 | 0 | 2 | .expx/memoria/ |
prodx | 6 | 6 | 0 | 0 | docs/produto/ |
buildx | 6 | 4 | 0 | 0 | docs/projeto/ |
A memox é a única que não grava nada em docs/: o índice dela é derivado,
descartável e gitignorado. A prodx e a buildx são as únicas sem hooks — e a
buildx é a única cujos artefatos descrevem um projeto, não um trabalho.
Começar
As três camadas de garantia
Uma regra escrita na skill é uma instrução — e instrução é coisa que o modelo pode esquecer na task 14 de uma execução longa, justamente quando o trabalho é grande e o risco é maior.
Todo hook de método nasce em modo aviso
| Modo | Comportamento | Quando promover |
|---|---|---|
aviso | registra no rastro, não bloqueia | estado inicial de todo hook de método |
bloqueio | barra a ação e devolve o motivo ao modelo | só depois de rodar semanas sem falso positivo |
desligado | não roda e não registra | desligar explicitamente um hook |
A razão é prática: hook que dá falso positivo é desinstalado, e junto com ele vão os que
funcionavam. A exceção são os hooks de segurança, que nascem em bloqueio e falham
fechados — segredo commitado não tem volta, e o falso positivo ali é raro.
O modo de cada hook vive em .expx/hooks.json:
{
"expx_hooks": 1,
"hooks": {
"escopo-da-task": { "modo": "aviso", "tipo": "metodo" },
"segredo": { "modo": "bloqueio", "tipo": "seguranca" }
}
}
Arquivo ausente, ilegível ou sem a entrada: hook de segurança assume bloqueio, hook de
método assume aviso. Só um desligado explícito desliga um de segurança.
Os agentes do ecossistema
| Agente | Usado por | Ferramentas | Papel |
|---|---|---|---|
auditor-plano | sprintx F5 | leitura apenas | Fura o plano antes de ele virar código |
revisor-testes | sprintx, runx | leitura apenas | Responde: esse teste passaria com a implementação errada? |
qa | runx E4 | leitura + rodar suíte | Valida contra os critérios; não corrige |
investigador | runx E1, sprintx F1 | leitura + busca | Monta a base e prova a causa raiz |
cartografo | stackx, legadox | leitura + histórico | Varre o repositório e extrai convenção ou perfil |
avaliador-de-raio | legadox C2 | leitura + escrita em docs/legado/raio/ | Coleta os oito sinais e classifica a faixa |
revisor-diff | mergex E3 | leitura + suíte | Classifica o diff nas três faixas de atenção |
analista-de-conflito | mergex E9 | leitura apenas | Explica o que cada lado pretendia; nunca resolve |
Um agente sem restrição declarada herda todas as ferramentas no Claude Code, o que
destruiria exatamente a garantia que justifica o agente existir. No Claude Code a restrição se escreve
tools: Read, Glob, Grep; no OpenCode não existe o campo tools — usa-se
permission: com edit: deny, write: deny, bash: deny.
Skill · base
sprintx
Planeja e executa features novas em seis fases: ingestão → descoberta → plano → orquestrador → auditoria → execução. Todo o esforço vai para o planejamento, e a execução é autônoma porque a ambiguidade já foi eliminada.
As fases
| Fase | Nome | O que produz |
|---|---|---|
F1 | Ingestão | base/00-INDICE.md, base/00-LACUNAS.md, um arquivo por recurso, 00-BLOQUEIOS.md |
F2 | Descoberta | 00-DECISOES.md — linhas D-NN e PENDENTE-NN |
F3 | Plano | sprint-NN/sprint.md, fases.md (com o grafo de tasks), tasks.md |
F3.5 | Estimativa opcional | 00-ESTIMATIVA.md |
F4 | Orquestrador | ORQUESTRADOR.md — oito seções fixas, na ordem |
F5 | Auditoria | 00-AUDITORIA.md — tabela de achados e a linha VEREDITO: |
F6 | Execução | atualiza tasks.md e fases.md; grava FECHAMENTO.md e apenda o histórico de estimativas |
A fase é detectada pelo disco
A skill nunca lê o .expx/estado.json para decidir onde está — ela olha o que existe:
| Estado do disco | Fase |
|---|---|
base/ não existe | F1 |
base/ existe, 00-DECISOES.md não | F2 |
00-DECISOES.md existe, sprint-01/ não | F3 |
sprint-01/ existe, ORQUESTRADOR.md não | F4 |
ORQUESTRADOR.md existe, sem auditoria aprovada | F5 |
00-AUDITORIA.md contém VEREDITO: SIM | F6 |
Comandos
| Comando | O que faz |
|---|---|
/sprintx | Detecta a fase atual e continua de onde parou |
/sprintx-base | F1 — ingestão, constrói a base de conhecimento |
/sprintx-descoberta | F2 — entrevista o usuário e registra as decisões |
/sprintx-sprints | F3 — gera o plano de sprints, fases e tasks |
/sprintx-estimar | F3.5 — estima o esforço em faixa, com premissas e confiança |
/sprintx-orquestrador | F4 — gera o ORQUESTRADOR.md |
/sprintx-auditoria | F5 — audita o plano e dá o veredito de prontidão |
/sprintx-executar | F6 — executa o plano auditado de forma autônoma |
No Claude Code os comandos ganham o namespace do plugin: /expx:sprintx-sprints.
No OpenCode ficam sem prefixo: /sprintx-sprints.
Agentes e hooks
| Hook | Evento | Modo | O que barra |
|---|---|---|---|
segredo | PreToolUse escrita | bloqueio | segredo com forma reconhecível indo para arquivo versionado |
git-perigoso | PreToolUse Bash | bloqueio | operação de versionamento irreversível durante a execução autônoma |
escopo-da-task | PreToolUse escrita | aviso | arquivo editado fora do campo arquivos da task em andamento |
task-so-fecha-verde | PreToolUse escrita | aviso | status: concluida com suíte ≠ verde ou faltando os dois testes |
sem-placeholder-no-plano | PostToolUse | aviso | marcador {{…}} de template não substituído |
tdd-teste-antes | PostToolUse | aviso | implementação nasceu antes do teste — inativo sem CONVENCOES.md |
Regras invioláveis
São vinte no total. As que mais governam o dia a dia:
- R2 — “As fases são estritamente sequenciais; nunca pule fase nem execute fora de ordem.”
- R3 — “TDD é obrigatório: o teste é escrito antes da implementação.”
- R4 — “Task só é marcada como concluída quando o teste de integração E o teste funcional passam; não existe ‘concluído com ressalva’.”
- R8 — “Dúvida nova durante a execução: registrar em
00-BLOQUEIOS.md, pular a task e seguir para a próxima paralelizável; nunca parar e esperar.” - R9 — “Na F1 nada de invenção: se a fonte não afirma, escreva
NÃO DOCUMENTADO; todo número vem com a referência que o afirma.” - R14 — “Na F5 a IA é auditora: só aponta, nunca corrige; achado de severidade ALTA manda voltar para a F3.”
- R15 — “Proibido escrever código de implementação em qualquer fase antes da F6.”
- R18/R19 — “Estimativa sai sempre como faixa… Número único é proibido.” / “Estimativa é esforço, nunca prazo de calendário.”
Artefatos em disco
docs/sprintx/features/<slug>/
00-BLOQUEIOS.md 00-DECISOES.md 00-ESTIMATIVA.md
ORQUESTRADOR.md 00-AUDITORIA.md FECHAMENTO.md
base/00-INDICE.md base/00-LACUNAS.md base/<recurso>.md
sprint-NN/sprint.md sprint-NN/fases.md sprint-NN/tasks.md
docs/sprintx/estimativas/HISTORICO.md # append-only, atravessa features
docs/eventos/<trabalho_id>.jsonl # rastro, gitignorado
Skill · base
runx
A metade Run: ocorrências de manutenção em produção, em cinco estágios — investigação com causa raiz comprovada, plano, fix sob TDD, QA independente e relatórios de fechamento.
Os estágios
| Estágio | Nome | O que produz |
|---|---|---|
E1 | Investigação | 00-OCORRENCIA.md, base/00-INDICE.md, base/00-LACUNAS.md, 01-CAUSA-RAIZ.md |
E2 | Plano | sprint-NN/sprint.md, fases.md, tasks.md, ORQUESTRADOR.md |
E3 | Fix | atualiza tasks.md; preenche BLOQUEIOS.md |
E4 | QA | QA.md com VEREDITO: APROVADO ou REPROVADO |
E5 | Relatório | docs/relatorios/<data>-<OC-ID>-<slug>/tecnico.md e uso.md; atualiza o INDICE.md |
QA.md reprovado volta para o E3. E há um retorno que o disco não mostra: se no
E3 o teste de regressão passar antes do fix, a ocorrência volta ao E1
— porque o que se acreditava ser a causa não era.
Os tipos de ocorrência governam o E1
Só bug exige causa raiz comprovada; os demais entram em análise de impacto.
Comandos
| Comando | O que faz |
|---|---|
/runx | Detecta o estágio atual e continua de onde parou |
/runx-causa | E1 — mapeia a base e comprova a causa raiz (ou mapeia o impacto) |
/runx-plano | E2 — converte a investigação em sprints, fases e tasks |
/runx-fix | E3 — implementa o plano sob TDD estrito, de forma autônoma |
/runx-qa | E4 — valida a entrega contra o plano e o escopo, sem corrigir |
/runx-relatar | E5 — relatórios técnico e de uso, e fechamento da ocorrência |
Hooks
Os hooks da runx rodam por um despachante único: cada
python3 custa cerca de 30 ms de partida, e cinco processos estourariam o orçamento de
200 ms por chamada de ferramenta.
| Hook | Modo | O que garante |
|---|---|---|
segredo-no-commit | bloqueio | barra credencial indo para arquivo versionado |
causa-antes-do-plano | aviso | plano sem 01-CAUSA-RAIZ.md, ou com comprovada: false num bug |
regressao-antes-do-fix | aviso | código de produção tocado antes de o teste de regressão existir |
task-so-fecha-verde | aviso | status: concluida sem suite: verde e sem os dois testes |
escopo-da-ocorrencia | aviso | escrita fora de arquivos_impactados e do arquivos das tasks |
sem-jargao-no-uso | aviso | caminho de arquivo, nome de função, tabela ou stack trace no relatório do cliente |
Regras invioláveis
- R1 — “Nenhum plano nasce sem
base/preenchida. Mapear antes de planejar.” - R2 — “Bug não avança de E1 sem causa raiz comprovada.”
- R5 — “O teste de regressão é escrito antes do fix e tem que falhar antes.”
- R8 — “Escopo travado: o que não está em
01-CAUSA-RAIZ.mde emtasks.mdnão é tocado — nada de refactor de brinde, nada de ‘já que estou aqui’.” - R10 — “Quem implementa não aprova: E4 é papel distinto de E3, e E4 não corrige nada.”
- R13 — “Durante E3 a skill não pergunta nada. Dúvida nova vira registro em
BLOQUEIOS.mde a task é pulada.” - R15 — “Coincidência de arquivo não é regressão. O campo
regressao_desó é preenchido com evidência de vínculo causal.”
Proporcionalidade: uma correção de uma linha gera 1 sprint, 1 fase e 2 tasks. “Proibido inflar o plano para parecer robusto. Proibido enxugar campos para parecer ágil.”
Skill · base
mergex
Versionamento, entrega e revisão: branch, um commit por task, portão de prontidão, descrição de PR, pacote de QA e abertura do pull request. O princípio que a governa: o revisor humano é recurso caro e finito.
As etapas
Não é uma máquina de estados sequencial: E0 e E1 acontecem durante a
execução do trabalho, E2–E8 acontecem no fim, e E9 é manual e avulsa.
| Etapa | Nome | O que produz |
|---|---|---|
E0 | Abertura | a branch do trabalho. “Branch que já existe é retomada, nunca duplicada” |
E1 | Commit por task | um commit por task fechada, com varredura de segredo antes de cada um |
E2 | Portão de prontidão | PRONTO ou BLOQUEADO. “BLOQUEADO encerra: a mergex não segue e não maquia” |
E3 | Atenção humana | ATENCAO.md — é o coração da skill |
E4 | Descrição do PR | PR.md — “Cabe em uma tela” |
E5 | Pacote para o QA | QA-PACOTE.md — “O QA não deve precisar ler código” |
E6 | Push | sobe a branch. “Nunca forçado, nunca na principal” |
E7 | Abertura do PR | abre pela CLI do serviço quando existir; ausente, grava em PR.md |
E8 | Registro da entrega | ENTREGA.md com kind: entrega |
E9 | Revisão e merge manual | conduz um PR por vez. “Nunca resolve conflito” |
As três faixas de atenção humana
O E3 classifica cada arquivo do diff em exatamente uma faixa, a partir de evidência já
registrada pelas outras skills — nunca de sensação.
| Faixa | O que o revisor faz | Critérios — basta um |
|---|---|---|
| OLHO OBRIGATÓRIO | Lê linha a linha | zona de risco do PERFIL.md; mudança de regra de negócio ou cálculo; migração de banco;
autenticação, autorização ou dado pessoal; alteração de contrato público; código sem cobertura antes e depois;
efeito irreversível; tudo que veio de raio ALTO; arquivo com histórico de regressão no memox |
| LEITURA RÁPIDA | Confere intenção, não implementação | mudança coberta por teste de caracterização que continua passando; alteração em camada isolada com cobertura existente; código novo em arquivo novo, com os dois testes verdes |
| DISPENSÁVEL | A máquina já provou | arquivo de teste que só acrescenta caso; alteração mecânica coberta por regressão verde; arquivo gerado automaticamente, quando declarado como tal |
Tamanho do diff não é critério. Uma linha que muda um cálculo fiscal é
OLHO OBRIGATÓRIO; trezentas linhas de teste novo são DISPENSÁVEL. E a faixa
nunca desce por causa do memox — o índice só agrava.
Comandos
| Comando | Etapas | O que faz |
|---|---|---|
/mergex | E2–E8 | Fluxo automático completo a partir do estado atual |
/mergex-abrir | E0 | Abre a branch antes da primeira linha de código |
/mergex-check | E2 | As dez verificações do portão de prontidão |
/mergex-atencao | E3 | Classifica o diff nas três faixas |
/mergex-pr | E4, E6, E7 | Monta a descrição, sobe a branch e abre o PR |
/mergex-qa | E5 | Gera o pacote de teste executável por quem não programa |
/mergex-revisar | E9 | só por chamada explícita revisão e integração de PRs |
O /mergex-revisar nunca é encadeado a partir de nenhum fluxo nem oferecido ao fim de um
trabalho: integrar código é decisão humana.
As dez verificações do portão
Regras invioláveis
- R1 — “A branch nasce com o trabalho, não no fim.”
- R3 — “Cada task concluída com suíte verde vira um commit próprio. Nunca amontoar tasks distintas.”
- R6 — “O portão de prontidão barra e explica. Nunca maquia.”
- R7 — “Nada na entrega é inventado: todo conteúdo vem de artefato existente.”
- R9 — “Zona de risco, migração de banco, mudança de contrato público e efeito irreversível são sempre
OLHO OBRIGATÓRIO.” - R11 — “Nunca push forçado, nunca na branch principal, nunca reescrever histórico já enviado.”
- R18 — “A mergex não faz merge no fluxo automático, não aprova, não publica e não faz deploy.”
- R19 — “A mergex entrega; quem fecha a ocorrência é a runx.”
Limitação declarada pela própria skill: a mergex não previne colisão entre desenvolvedores. Ela organiza a entrega de um trabalho; coordenar duas pessoas no mesmo arquivo continua sendo problema de processo humano.
Skill · camada
legadox
Camada que endurece o trabalho em projetos legados. Não acrescenta fase: muda o rigor de cada uma, proporcional ao raio de impacto da mudança. Em código legado o comportamento atual é o contrato, bugs inclusive.
O gatilho é um arquivo. Sem docs/legado/PERFIL.md não existe modo
legado. A primeira coisa a fazer é gerá-lo, com /legadox-perfil.
O raio de impacto
Oito sinais coletados por evidência — chamadores, telas e rotas, consumo assíncrono, cobertura, zona de risco, churn e idade, migração, dado histórico. Sinal que não puder ser coletado conta como pior caso, e isso fica escrito.
BAIXO exige que
todas as condições valham juntas; MEDIO e ALTO bastam uma.O que cada faixa aciona
| Camada | BAIXO | MEDIO | ALTO |
|---|---|---|---|
| Raio registrado C2 | sim | sim | sim |
| Prova de código vivo C10 | sim | sim | sim |
| Proibição de colateral C6 | sim | sim | sim |
| Testes de caracterização C3 | — | sim | sim |
| Ponto de costura C4 | — | sim | sim |
| Orçamento por task C5 | 5 arq / 150 linhas | 3 arq / 80 linhas | 2 arq / 40 linhas |
| Plano de reversão C7 | — | sim | sim |
| Roteiro de teste manual C8 | — | sim | sim |
| Plano aprovado antes do código | — | sim | sim |
| Perguntas da zona C11 | — | se tocar zona | sim |
| Comparação com dado real C9 | — | — | sim |
| Chave de desligamento | — | — | sim |
| Aprovação humana registrada | — | — | sim |
A camada 9 é obrigatória, independentemente da faixa, em qualquer mudança de cálculo ou de regra de negócio.
Nenhum hook de método roda em raio BAIXO. Todos leem a faixa primeiro e saem
imediatamente. A exceção é o zona-de-risco, que bloqueia em qualquer faixa.
Comandos
| Comando | Camada | O que faz |
|---|---|---|
/legadox | — | Verifica o modo legado e mostra o que falta no trabalho atual |
/legadox-perfil | C1 | Gera ou atualiza o PERFIL.md, o gatilho do modo legado |
/legadox-raio | C2 | Calcula o raio por evidência e declara quais camadas isso aciona |
/legadox-caracterizar | C3 | Escreve os testes que congelam o comportamento atual |
/legadox-divida | C6 | Consulta e acrescenta ao inventário de dívida, sem corrigir |
/legadox-manual | C8 | Gera o roteiro de teste manual, com a seção de colateral |
Regras invioláveis
- “Sem
docs/legado/PERFIL.mdnão existe modo legado. A primeira coisa é gerá-lo.” - “Nenhum plano é gerado sem o raio de impacto calculado e escrito.”
- “A faixa do raio é calculada por sinais, nunca escolhida por sensação.”
- “Em raio MEDIO ou ALTO, nada é alterado antes de existir teste de caracterização passando no código atual.”
- “Nenhuma melhoria colateral. O que incomoda vai para
docs/legado/DIVIDA.md.” - “O orçamento de mudança por task não é estourado em silêncio.”
- “Toda task de raio MEDIO ou ALTO declara como se reverte, inclusive os efeitos que o versionador não desfaz.”
- “Zona de risco tocada obriga as perguntas da zona respondidas antes do plano.”
- “Raio ALTO obriga aprovação humana explícita e registrada.”
- “Código morto identificado não é removido: vira achado.”
- “Dado real usado em comparação é anonimizado e nunca é commitado.”
- “O legadox não substitui a sprintx nem a runx: ele os endurece.”
Artefatos em disco
docs/legado/PERFIL.md # C1 — gatilho do modo legado
docs/legado/LACUNAS.md
docs/legado/DIVIDA.md # C6 — append-only
docs/legado/raio/<trabalho_id>.md # C2
docs/legado/manual/<trabalho_id>.md # C8
docs/legado/comparacao/<trabalho_id>.md # C9
Skill · camada
stackx
Descobre o dialeto técnico do repositório — onde os testes moram, como o banco é isolado, quais comandos funcionam de verdade, quem pode chamar quem — e grava tudo com evidência. Convenção não se propõe, se descobre.
As etapas
| Etapa | Nome | O que produz |
|---|---|---|
1 | Detecção | inventário FATO / EVIDÊNCIA / FORÇA em memória — roda no agente cartografo |
2 | O CONVENCOES.md | docs/stack/CONVENCOES.md |
3 | Conflito e lacuna | docs/stack/LACUNAS.md |
4 | Verificação de aderência | tabela severidade / arquivo / convenção violada / correção sugerida |
5 | Atualização | diff sobre o CONVENCOES.md — nunca sobrescreve em silêncio |
A ordem da detecção
Não é arbitrária: vai do que declara a intenção para o que revela a prática.
- manifestos e locks
- configuração de runner, lint, formatador, type checker e build
- os testes que já existem — a fonte mais rica
- migrações e schema
- scripts dos manifestos
- integração contínua
- arquivos de ambiente de exemplo
- o próprio código
Os três cartuchos
Um cartucho só existe quando o assunto é, ao mesmo tempo, não óbvio, específico de versão ou engine e caro de errar.
O que trava tabela e por quanto tempo, índice sem bloqueio, coluna obrigatória em tabela grande, ordem segura de renomear em deploy sem indisponibilidade, e o que fazer quando reverter não é possível.
Consultas que explodem em produção e passam nos testes com massa pequena.
Estado global, paralelismo sem isolamento de banco, relógio, ordem, fuso e rede.
Comandos
| Comando | O que faz |
|---|---|
/stackx | Sem CONVENCOES.md, conduz à detecção; com ele, mostra o resumo, as lacunas e os pontos marcados PROPOSTA |
/stackx-detectar | Etapas 1 e 2 — varre em busca de evidência real e gera os dois arquivos |
/stackx-check | Etapa 4 — verifica se um diff respeitou as convenções. Aponta, não corrige |
/stackx-atualizar | Etapa 5 — redetecta e apresenta o diff. Nunca sobrescreve em silêncio |
/stackx-migracao | Consulta dirigida ao cartucho de migração segura |
Regras invioláveis
- “Toda convenção aponta um arquivo real do repositório que a exemplifica, com caminho e linha.”
- “Convenção sem evidência no código não é convenção: é
PROPOSTA, e é marcada como tal.” - “
PROPOSTAnão governa. Nas outras skills ela vira decisão a levantar, nunca regra a obedecer.” - “Diante de dialetos conflitantes, o stackx não escolhe sozinho: apresenta os dialetos com contagem e histórico, e pergunta.”
- “Comando declarado precisa ter sido encontrado em manifesto, script ou integração contínua. Comando nunca é inferido do nome do framework.”
- “Em projeto legado, na área tocada manda o
PERFIL.mddo legadox. O stackx governa apenas código novo em arquivo novo.” - “Atualização de convenção nunca sobrescreve em silêncio: apresenta diff e espera confirmação.”
- “A verificação de aderência aponta, não corrige.”
- “Cartucho não repete o que o modelo já sabe. Se virou tutorial de sintaxe, foi escrito errado.”
- “Nenhum segredo, credencial ou dado real de cliente entra em
CONVENCOES.md, exemplo ou template.”
O formato obrigatório da evidência é literal:
Evidência: src/users/create-user.test.ts:14, src/orders/place-order.test.ts:9
O CONVENCOES.md liga hooks de outras skills. O
tdd-teste-antes e o escopo-da-task da sprintx, a convenção de commit e branch da
mergex e o comando de teste de todas ficam inativos quando o arquivo não existe.
Skill · camada
memox
Indexa o que as outras skills já gravaram e responde o que se sabe sobre um arquivo antes de alguém mexer nele. Memória que precisa ser consultada não é usada — por isso ela se injeta sozinha no contexto.
Índice invertido, não busca semântica
A pergunta real não é “o que é parecido com isto”, é “quem já mexeu neste arquivo e por quê” — e isso é uma string exata. Resposta de índice aponta artefato e data, então dá para abrir e conferir; recuperação semântica erra em silêncio, devolvendo algo plausível com a mesma confiança do certo.
O que ele indexa
| Fonte | O que extrai |
|---|---|
docs/relatorios/*/tecnico.md | trabalho, data de fechamento, tipo, módulo afetado, arquivos alterados, causa em uma linha, risco residual |
docs/relatorios/INDICE.md | a linha do tempo, para ordenação e contagem |
docs/manutencao/*/01-CAUSA-RAIZ.md | modo, se é comprovada, arquivos impactados, decisões |
00-DECISOES.md | cada decisão com a alternativa descartada e o motivo |
docs/legado/DIVIDA.md | dívida observada por arquivo, com risco estimado |
base/00-LACUNAS.md | o que a documentação não respondia |
docs/manutencao/*/QA.md | reprovações — o sinal mais forte de área frágil |
docs/entregas/*/ENTREGA.md | branch, commits e faixa de atenção por arquivo |
Regressão exige evidência causal, não coincidência
Um vínculo só é registrado como regressão quando as três condições valem juntas: um arquivo apontado pela
causa raiz do trabalho posterior está entre os que o anterior alterou; a ordem cronológica está estabelecida;
e a causa do posterior é comprovada, não hipótese. Faltando qualquer uma, o vínculo aparece
como coincidencia_arquivo com o motivo escrito — é isso que impede o sinal mais valioso do
índice de virar ruído.
Comandos
| Comando | O que faz |
|---|---|
/memox | Estado do índice: quantos trabalhos, quando foi reconstruído, o que ficou de fora e por quê |
/memox-indexar | Reconstrói o índice do zero a partir dos artefatos |
/memox-arquivo | O que se sabe sobre um arquivo — quem o tocou, quando, e se já causou regressão |
/memox-modulo | Histórico de um módulo, com as decisões e suas alternativas descartadas |
/memox-buscar | Busca textual nos títulos, causas e resumos dos trabalhos fechados |
Os dois hooks falham abertos
| Hook | Evento | O que faz |
|---|---|---|
memox-injetar | UserPromptSubmit | detecta os arquivos que o prompt declara que serão tocados e injeta o que se sabe sobre eles, com proveniência |
memox-reindexar | Stop | reconstrói o índice quando detecta artefato novo ou alterado, de forma assíncrona |
Contrato dos dois: silencioso quando não há nada relevante; sai com 0 sempre, inclusive
em erro; abaixo de 200 ms; sem rede e sem modelo.
É por isso que o doctor trata “hook sem motor” como erro. Falha aberta
nunca trava o prompt de quem está trabalhando — o preço é que uma instalação quebrada fica indistinguível
de um projeto sem artefatos. O doctor é o único lugar onde a diferença aparece.
Controle de ruído
No máximo 3 entradas recentes por arquivo, mais as que envolveram regressão,
reprovação em QA ou zona de risco. Acima de 8 entradas relevantes ele não lista: informa a
contagem. Tudo configurável em .expx/memoria/config.json.
python3 .claude/skills/memox/assets/memox.py indexar
O índice fica em .expx/memoria/indice.json, é local e gitignorado, e se reconstrói do zero a
qualquer momento. Um clone recém-feito não tem nenhum — esse é o caso comum, não um erro.
Skill · camada
prodx
Recebe o pedido cru, tria, verifica se o que foi pedido já existe e emite um veredito com evidência para assinatura humana. O cliente pede solução, não problema.
O indicador de sucesso declarado pela skill é a taxa de pedidos que NÃO viram trabalho. Três dos quatro vereditos encerram o pedido sem gerar uma linha de código.
Os estágios
| Estágio | Nome | Saída | Quando roda |
|---|---|---|---|
P0 | Triagem | linha em docs/produto/INDICE.md — não gera pasta | todo pedido |
P1 | Contexto de produto | PRODUTO.md e LACUNAS.md | uma vez, atualizado sob demanda |
P2 | Entendimento do pedido | 01-pedido.md | avaliação completa |
P3 | Verificação de existência | 02-existencia.md | avaliação completa |
P4 | Avaliação | 03-avaliacao.md | quando não for ja_existe |
P5 | Veredito e briefing | VEREDITO.md e BRIEFING.md | avaliação completa |
Os oito gatilhos da triagem
Nenhum gatilho disparado: veredito direto, uma linha no índice, segue para a runx. Um ou mais: avaliação
completa, de P2 a P5.
| Gatilho | |
|---|---|
G1 | O pedido é do tipo novo, ou pede tela, relatório ou fluxo novo |
G2 | O pedido descreve uma solução, não um problema |
G3 | O pedido serve a um cliente só, num produto multi-cliente |
G4 | O pedido cheira a algo que já existe no sistema |
G5 | O pedido chegou rotulado como bug mas descreve regra de negócio |
G6 | O pedido toca zona de risco declarada no PERFIL.md |
G7 | O mesmo pedido já foi recusado antes |
G8 | O esforço aparente é maior que alguns dias |
Os quatro vereditos
| Veredito | Significado |
|---|---|
| ja_existe | O sistema já faz. Sai um texto para o cliente explicando onde e como, na linguagem dele |
| nao_fazer | Com o motivo registrado. Este arquivo é ativo permanente: quando o pedido voltar, a avaliação já está feita |
| fazer_outra_coisa | O problema real reformulado, que costuma ser menor e diferente do pedido |
| fazer | E aí sai o briefing |
O VEREDITO.md traz sempre um campo de assinatura humana, preenchido pela
pessoa, nunca pela skill.
Comandos
| Comando | O que faz |
|---|---|
/prodx | Mostra os pedidos abertos e a proporção entre triagem e avaliação completa |
/prodx-produto | P1 — cria ou atualiza o contexto de produto que sustenta todos os vereditos |
/prodx-triar | P0 — roda os oito gatilhos. Seco e rápido, sem criar pasta |
/prodx-avaliar | P2 a P5 — avaliação completa até o veredito pronto para assinatura |
/prodx-existe | P3 isolada — “isso já existe?”, com evidência |
/prodx-briefing | Gera o BRIEFING.md no formato que a sprintx ou a runx espera |
Regras invioláveis
- “A skill não decide. Ela recomenda com evidência; humano assina.”
- “Nenhum trabalho segue para sprintx ou runx sem veredito assinado.”
- “A triagem nunca é pulada, e a avaliação completa nunca roda em pedido sem gatilho disparado.”
- “A solução pedida nunca é tratada como o requisito. O requisito é o problema.”
- “A verificação de existência é obrigatória e vem com evidência: tela, rota, arquivo ou relatório. ‘Acho que já tem’ não é resposta.”
- “Escopo mínimo é campo obrigatório e nunca fica vazio.”
- “Pedido rotulado como bug é verificado contra comportamento intencional antes de virar ocorrência.”
- “Informação que falta vira pergunta, nunca suposição.”
- “Pedido recusado não é apagado: a avaliação é ativo permanente.”
- “O briefing não contém decisão técnica.”
- “Nada de invenção no
PRODUTO.md. O não verificável viraNAO DETERMINADO.” - “O campo de quem assina nunca fica vazio.”
Skill · orquestração
buildx
Recebe a descrição de um projeto inteiro em linguagem natural, faz uma única pergunta, e conduz as outras skills até o sistema estar construído, testado e validado. Uma descrição entra, um sistema sai.
Ela não implementa, não planeja e não escreve teste nenhum. Toda a competência
mora nas camadas irmãs. A única coisa que a buildx faz e nenhuma outra faz é a
decomposição: quebrar um projeto em features. É o vão entre “quero um sistema de gestão
de contratos” e “planejar a feature de upload de PDF” — a sprintx planeja uma
feature com rigor e não sabe recortar um sistema.
A pergunta única
É a primeira coisa que acontece, antes de qualquer arquivo:
| Modo | O que significa |
|---|---|
| autônomo total | Nenhuma outra pergunta chega ao usuário até o fim — nem da buildx, nem de nenhuma camada que ela invocar. Cada decisão tomada em nome dele vira uma premissa registrada, com o fato que a invalidaria |
| briefing | Uma rodada de perguntas, no máximo dez, só as que mudam a arquitetura. Respondidas, o comportamento é idêntico ao autônomo: silêncio até o fim |
Relatar progresso não é perguntar: nos dois modos o usuário vê onde a cadeia está, sem precisar responder nada.
As seis etapas
| Etapa | Nome | O que acontece | Quem trabalha |
|---|---|---|---|
B1 | Concepção | mapeia o escopo e varre o que não foi pedido; cada lacuna vira premissa | prodx, modo greenfield |
B2 | Fundação | escolhe a stack, instala a suíte, monta o esqueleto que sobe e testa | stackx, invertido |
B3 | Decomposição | quebra o projeto em features, com ordem de dependência | só a buildx |
B4 | Construção | o laço: por feature, branch → plano → auditoria → execução TDD → PR | sprintx, mergex |
B5 | Recursão | classifica o que ficou pelo caminho e devolve ao laço o que a máquina resolve | buildx |
B6 | Validação | confere o construído contra o mapa, item a item, e relata | prodx, como auditor |
O ciclo B4 → B5 repete enquanto houver pendência que a máquina resolve, com
teto de três ciclos. O ciclo 2 resolve o que o B3 recortou mal; o 3 resolve o
que o 2 criou. Do quarto em diante o que sobra normalmente não é falta de trabalho, é falta de decisão.
O que ela descobre que você não pediu
A varredura do B1 é a razão de a buildx existir em vez de você falar direto com
a sprintx. Trinta e um eixos, percorridos sempre — cada um sai como pedido,
descoberto ou descartado com o porquê registrado. Nenhum é pulado em silêncio.
| Grupo | Exemplos do que entra sem ninguém pedir |
|---|---|
| Segurança | autorização por papéis desde a primeira feature, hash de senha, rate limit nas rotas de autenticação, validação de entrada no servidor |
| Dado e conformidade | LGPD com exclusão que apaga de fato e exportação do titular, trilha de auditoria, backup com restauração testada |
| Operação | log sem dado pessoal, erro que não vaza rastro de pilha, rota de saúde, variável obrigatória que falha no start e não em produção |
| Interface | as duas variantes de tema completas, estados de vazio, carregando e erro, responsividade, contraste conferido |
Toda decisão fica auditável
Cada escolha feita em nome do usuário vira uma premissa com cinco campos, e o quinto é o que importa:
PR-07 — Autorização por papéis
Decisão: papéis admin e usuario desde a primeira feature,
verificados no servidor.
Por quê: o sistema tem dado de mais de um usuário; sem papel,
qualquer conta alcança o dado de qualquer outra.
O que
invalida: se todo usuário tiver exatamente o mesmo acesso aos
mesmos dados, de forma permanente.
Como revisar vinte e três decisões em cinco minutos: leia só o campo o que invalida. Se aquilo é verdade no seu caso, a premissa merece atenção. Se não é, siga.
A fronteira que ela não atravessa
A buildx decide como o sistema se protege, não o que o sistema faz.
Requisito não-funcional tem padrão defensável por classe de sistema — um sistema sem rate limit tem um defeito conhecido. Regra de negócio não tem padrão: ela é o negócio. Um sistema com a regra de cálculo errada funciona e está errado, que é o pior resultado possível, porque parece pronto e ninguém procura o defeito.
Regra de negócio não declarada nunca é chutada: vira pendência, a buildx segue com a
decisão mais reversível possível, e o relatório final abre com ela.
O que ela quebra de propósito
O modo autônomo viola regras que existem por bons motivos nas irmãs. Cada violação é restrita ao modo e registrada no artefato que ela toca.
| Regra violada | De quem | Como fica |
|---|---|---|
| “a skill não decide, humano assina” | prodx R1 | a buildx assina, com provisorio: true e aprovado_por: buildx (modo autonomo) |
| “nada vai à sprintx sem veredito assinado” | prodx R2 | a auto-assinatura satisfaz o portão |
| “a F2 é obrigada a perguntar ao humano” | sprintx R10 | a buildx responde em quatro degraus — PROJETO.md, PREMISSAS.md, CONVENCOES.md, e só então uma premissa nova — tudo em 00-DECISOES.md com respondido_por: buildx |
| “convenção só se registra com evidência” | stackx | no B2 a origem é decidido_pelo_buildx; depois da primeira feature entregue, o stackx-detectar converte cada regra para a evidência real |
O que ela nunca quebra. O merge continua humano: a
buildx nunca invoca mergex-revisar, nunca oferece, nunca sugere. Todas as outras
coisas que ela faz sozinha são reversíveis — uma premissa errada se corrige, um plano ruim se replaneja.
Merge é onde o trabalho vira o sistema. Um buildx que faz merge sozinho não é mais autônomo: é
irreversível, e são coisas diferentes.
Também intactos: o TDD da sprintx, a regra de que task só conclui com os dois testes
passando, e a auditoria da F5 — execução autônoma sem auditoria respeitada é dano autônomo.
Os padrões da casa
O que a buildx assume quando o usuário não diz nada. O usuário sempre ganha do padrão.
| Padrão | Por quê | |
|---|---|---|
P-1 | três camadas, fronteira explícita | é o desenho que o stackx sabe verificar e a sprintx sabe recortar em tasks |
P-2 | Next.js, TypeScript, App Router | cobre as três camadas num único projeto e num único deploy |
P-3 | SQLite local | dependência mínima é requisito de execução autônoma: um banco que exige serviço, credencial e rede é um ponto onde o laço trava esperando algo que a máquina não resolve |
P-4 | autenticação própria, JWT, hash forte | não depende de provedor externo nem de credencial que a buildx não tem |
P-5 | usuário de demonstração com dados de exemplo | um sistema que sobe numa tela de login vazia é indistinguível de um sistema quebrado |
P-6 | o design system do VS Code | tokens semânticos e par claro/escuro já resolvidos — e uma regra verificável: nenhuma cor literal em componente |
P-7 | a skill de frontend design da Anthropic | trabalha dentro desses tokens; a competência de design mora numa skill feita para isso |
P-8 | o projeto nasce com a suíte Expx instalada | o B4 precisa dela, e quem receber o sistema continua usando o método — o memox só vale se estiver lá desde o primeiro commit |
Comandos
| Comando | O que faz |
|---|---|
/buildx <descrição> | o comando único: recebe a descrição, faz a pergunta do modo, e conduz tudo até o fim |
/buildx | roteador: mostra em que etapa o projeto está, e o estado de cada feature |
/buildx-mapa | B3 isolada — mostra ou regera o MAPA.md |
/buildx-retomar | retoma um projeto interrompido, a partir do estado em disco |
/buildx-status | painel seco: features, ciclos de recursão, pendências, premissas |
Artefatos em disco
docs/projeto/
PROJETO.md o escopo: o pedido, o descoberto, o descartado
PREMISSAS.md toda decisão tomada em nome do humano
MAPA.md as features, em ordem de dependência
RECURSAO.md pendências por ciclo, e o teto
VALIDACAO.md a conferência final
RELATORIO.md o que o usuário lê no fim
São os únicos artefatos do método que descrevem um projeto e não um trabalho: usam
projeto_id no lugar de trabalho_id. A ponte entre os dois níveis são as chaves
origem_buildx e feature_id, que a cadeia acrescenta ao artefato de cada feature —
é o que permite abrir um plano de sprint qualquer e saber de qual projeto ele veio.
O que o usuário lê no fim
1. O QUE VOCÊ PRECISA DECIDIR as regras de negócio não declaradas
2. O QUE VOCÊ PRECISA PROVIDENCIAR credenciais, acessos, contas
3. O QUE FOI DECIDIDO POR VOCÊ as premissas, com o que invalida cada uma
4. O QUE FICOU PRONTO features entregues, com os PRs
5. O QUE NÃO FICOU pendências, com o porquê
6. COMO RODAR instalar, subir, entrar com o usuário demo
7. O QUE FAZER AGORA revisar os PRs e fazer merge
A ordem é deliberada: o que exige ação vem antes do que foi feito. Um relatório que abre com onze features entregues e esconde na página três que a regra de cálculo foi chutada é desonesto na estrutura, mesmo dizendo tudo.
Regras invioláveis
- “Uma única pergunta ao usuário: o modo. No autônomo, nenhuma outra chega a ele, de nenhuma camada.”
- “Toda decisão tomada no lugar do humano é registrada em
PREMISSAS.mdantes de ser usada, com o que a invalidaria.” - “A buildx não implementa, não planeja e não testa. Ela invoca a camada dona e verifica a saída.”
- “Bloqueio nunca para o laço: registra, marca a feature, segue para a próxima.”
- “O ciclo B4 → B5 tem teto declarado. Atingido, para e reporta.”
- “Nenhuma feature entra no mapa sem entrega verificável e dependências explícitas.”
- “Feature de fundação vem primeiro; nenhuma feature precede aquilo de que depende.”
- “Merge é humano. Nunca invoca
mergex-revisar, nem oferece.” - “O que não for derivável do projeto, das premissas ou das convenções vira premissa nova — nunca invenção silenciosa.”
- “Todo artefato usa o frontmatter
expx-schema v1.” - “Caminhos sempre relativos.”
- “O relatório final declara toda pendência.”
Referência do CLI
Subcomandos
Sete subcomandos. O panel e o watch funcionam sem
init: nenhum dos dois escreve no projeto.
| Comando | O que faz |
|---|---|
expx init | Instala as skills escolhidas neste projeto |
expx panel | Sobe o painel de operação lendo o docs/ do projeto |
expx watch | Acompanha um trabalho no terminal, ao vivo |
expx add <skill…> | Acrescenta skills à seleção e remonta o plugin |
expx remove <skill…> | Remove skills da seleção e remonta o plugin |
expx update [skill…] | Atualiza as skills instaladas |
expx doctor | Diagnostica uma instalação quebrada |
O pacote publica três binários: expx e expxdev (o mesmo programa) e
expx-painel, que sobe o painel direto.
init
expx init [--skills a,b] [--harness claude,opencode] [--yes]
Sem --skills e com terminal interativo, abre o assistente. Sem --yes e sem TTY,
imprime o que instalaria e sai sem escrever. Uma skill que falha não derruba as outras: o erro dela é
reportado nominalmente e o init segue com as demais.
add e remove
expx add memox prodx
expx remove legadox
Os dois leem o lock, ajustam a seleção e remontam o plugin do zero com o mesmo harness
já registrado. Sem instalação válida, o CLI orienta a rodar o init. Remover a última skill é
recusado: uma instalação vazia não é estado válido.
update
| Flag | Efeito |
|---|---|
| (sem argumento) | Atualiza todas as skills instaladas |
<skill…> | Atualiza apenas as nomeadas |
--check | Só mostra o que mudaria, não aplica nada |
--to <ref> | Fixa uma skill numa tag ou commit — exige nomear exatamente uma skill |
--yes · --sim | Aplica sem exigir terminal interativo |
doctor
Não aceita flags. Sai com 0 quando não há nenhum achado de severidade erro —
ou seja, só avisos ainda sai 0, mas a lista é impressa.
panel e watch
| Comando | Flag | Padrão | O que faz |
|---|---|---|---|
panel | --porta <n> | 4000 | porta do servidor local |
--dir <caminho> | ./docs | pasta de documentação a observar | |
--no-open | — | não abre o navegador | |
--dias-bloqueio <n> | 7 | dias a partir dos quais um bloqueio é antigo | |
watch | <trabalho_id> | — | segue um trabalho específico |
--todos | — | lista os trabalhos abertos, sem árvore | |
--colunas <n> | largura do terminal | largura fixa |
Os dois aceitam --ajuda, --help ou -h, e a forma
--flag=valor.
Flags aceitas que ainda não têm efeito. O parser reconhece --painel
e --check no init, e --latest no update, mas nenhuma
delas altera o comportamento nesta versão. O dry-run efetivo do init é a ausência de
--yes fora de um terminal interativo; a resolução do update já é sempre a maior
tag. Não existe expx --version: a versão aparece no cabeçalho do init interativo.
Referência do CLI
Anatomia do init
O que roda, em que ordem, e por quê.
Para cada skill selecionada
Resolve a versão alvo
Busca a maior tag de versão semântica do repositório — comparando número a número, porque ordenar como texto colocaria
v1.10.0antes dev1.2.0. Pré-lançamento (-rc.1) é ignorado: não é versão publicada. Sem nenhuma tag, cai para a branch padrão e registratravado: falseno lock.Busca o conteúdo
Com
git clone --depth 1 --branch <referência>, usando ogitdo sistema. É de propósito: assim aproveita a credencial já configurada na máquina e não esbarra em limite de requisição de API.Detecta o layout
Os repositórios não têm todos a mesma forma. O CLI não assume caminho: procura o
SKILL.mdmais raso e adota a pasta dele como raiz, depois confere que oname:do frontmatter é mesmo a skill pedida. Um layout novo passa a funcionar sem tocar nesta camada.Verifica os caminhos
Recusa qualquer skill que referencie caminho fora da própria pasta. A mensagem traz até três achados, no formato
arquivo:linha → referência.Calcula o hash de cada arquivo
SHA-256 por arquivo, registrado no lock junto com repositório, referência, commit e a data de resolução.
Por que “caminho fora da própria pasta” é recusado. Ao instalar, o Claude Code
copia o plugin para ~/.claude/plugins/cache/…, e só a pasta do plugin vai junto.
Qualquer ../ dentro de uma skill sai da árvore copiada e deixa de resolver — silenciosamente.
O CLI recusa instalar uma skill assim, tanto no init quanto no doctor.
Só depois é que a escrita acontece
E ela é atômica: a montagem inteira ocorre numa pasta temporária ao lado do
destino — não em /tmp, porque rename só é atômico dentro do mesmo sistema
de arquivos — e é trocada por rename ao final. Se falhar no meio, o .expx/ anterior
é devolvido ao lugar e permanece intacto.
A configuração do harness
A configuração do Claude Code é mesclada, nunca reescrita: backup datado antes de
qualquer alteração, todo o resto preservado, e recusa explícita de “consertar” JSON inválido — nesse caso o
arquivo não é tocado e o init emite um aviso.
Duas particularidades medidas em execução, não presumidas:
- A lista de plugins habilitados é lida nos dois formatos — o array documentado e o objeto que o Claude Code realmente escreve — e sempre gravada como objeto.
- Os hooks só entram na configuração se houver hooks. Um projeto sem skill com hook não
ganha uma seção vazia do nada. E a entrada é deduplicada pelo comando, porque o
initroda de novo a cada atualização e a duplicata faria o hook rodar duas vezes por prompt.
Hooks no disco
Quando alguma skill traz hook, o CLI copia a skill inteira para
.claude/skills/<nome>/ e o script para .claude/hooks/, com
chmod 0755 — sem o bit de execução o hook não roda e não avisa. A skill vai junto porque o hook
resolve o próprio motor como um caminho relativo a si mesmo.
Claude Code e OpenCode lado a lado
| Aspecto | Claude Code | OpenCode |
|---|---|---|
| Skills | no plugin; e em .claude/skills/ quando há hook | .claude/skills/ — sempre, todas |
| Comandos | no plugin, com namespace /expx:… | .opencode/commands/, sem prefixo |
| Manifestos | plugin.json + marketplace.json | nenhum |
| Configuração | mesclada, com backup | não escreve configuração |
| Registro | claude plugin marketplace add e install | nenhum comando externo |
| Hooks | copiados e registrados | lacuna declarada |
As skills vão somente para .claude/skills/, que o OpenCode lê nativamente.
Copiar também para .opencode/skills/ criaria dois name iguais nas pastas que o
OpenCode varre, e a duplicata é resolvida por último-a-escrever-vence com apenas um aviso no log —
silenciosamente. É exatamente essa colisão que o doctor detecta.
Referência do CLI
/expx:onboarding
A primeira coisa a rodar depois do init. Sem ela, cada camada instalada roda
em modo degradado na primeira vez que alguém a usa — e essa lacuna só aparece no meio de um plano, quando
já custou tempo.
stackx, designx, legadox, memox e
prodx já sabem cada uma mapear a própria camada. O que faltava era quem decidisse, na
primeira vez que alguém abre um projeto com várias instaladas, o que já foi mapeado, o que
falta, e em que ordem rodar o resto — em vez da pessoa descobrir isso comando por comando.
/expx:onboarding
Comando fixo do plugin, não de uma skill
Nenhuma camada é dona do onboarding — ele só orquestra as que já existem. Por isso ele mora em
nucleo/commands/onboarding.md deste repositório, e viaja sempre para
commands/ na raiz de todo plugin montado, junto com as skills selecionadas — do mesmo jeito
que o resto do nucleo/ viaja por cópia. Está disponível mesmo que você não tenha escolhido
nenhuma camada de mapeamento: nesse caso ele avisa, em uma linha, que não há nada para orquestrar.
Ele nunca reimplementa o critério de detecção de nenhuma camada — só lê o artefato que cada uma produz e chama o comando de verdade.
O que ele faz, em ordem
Descobre o que está instalado
Entre as cinco camadas que produzem mapeamento inicial.
runx,sprintx,mergexebuildxnunca entram nesta lista — elas só consomem o que essas cinco geram.Verifica o que já foi mapeado
Pela presença do artefato de cada camada. Camada já mapeada nunca é sobrescrita — redetecção é trabalho de cada uma (
/stackx-atualizare equivalentes), não deste comando.Monta a fila só com o que é pendente
Na ordem de dependência:
prodx→stackx→designx→legadox→memox.designxsó entra com sinal de UI no projeto;stackxsó com sinal de código de verdade;legadoxpergunta uma vez — legado é decisão de quem conhece o projeto, nenhuma evidência de código prova isso sozinha.Executa uma camada de cada vez
Nunca em paralelo: uma pode se apoiar no que a anterior deixou (
designxreferenciastackx, por exemplo). Camada que falha é registrada e não derruba as outras.Fecha com uma tabela-resumo
Instalada, estado antes, ação tomada, artefato gerado — e uma linha final dizendo o que mudou.
O gatilho de cada camada
| Camada | Gatilho | Artefato |
|---|---|---|
prodx | sempre disponível — o roteador /prodx decide se convoca o P1 | docs/produto/PRODUTO.md |
stackx | CONVENCOES.md ausente + sinal de código de verdade | docs/stack/CONVENCOES.md |
designx | DESIGN-SYSTEM.md ausente + sinal de UI (.tsx/.jsx/.css) | docs/design-system/DESIGN-SYSTEM.md |
legadox | confirmação humana — pergunta uma vez, nunca por evidência de código | docs/legado/PERFIL.md |
memox | ao menos um artefato de trabalho fechado já existente | .expx/memoria/indice.json |
Por que legadox não é evidência automática. Legado é decisão de quem conhece o projeto — não algo que sinal de código prova sozinho. Por isso é a única camada da fila que faz uma pergunta direta antes de agir, em vez de decidir pela estrutura do repositório.
Referência do CLI
Lock e atualização
A instalação é travada por lock; a atualização é um ato explícito. Quem clona o projeto recebe exatamente as mesmas skills que o time está usando, sem rede e sem rodar nada.
O formato do lock
{
"lock_version": 1,
"cli_version": "0.5.0",
"harness": ["claude"],
"skills": {
"sprintx": {
"repositorio": "https://github.com/bittencourtthulio/sprintx",
"referencia": "main",
"travado": false,
"commit": "4e3570c9bb19b8e336a5ca9c22ea17e7394dc6e8",
"resolvido_em": "2026-08-29",
"arquivos": {
"SKILL.md": "e3b0c442…b855"
}
}
}
}
travado: false significa que a skill segue uma branch, e não uma tag publicada — é o estado
atual de todas as oito, porque nenhum dos repositórios publica tag ainda. O doctor reporta isso
como aviso, nunca como erro.
O que o update faz
- Descobre a versão alvo de cada skill instalada
- Compara com o lock — skill já em dia é reportada e não é tocada
- Detecta modificação local: se os arquivos divergirem do lock, não sobrescreve
- Mostra o resumo por skill: versão atual, versão nova, e os títulos dos commits entre as duas
- Pede confirmação e aplica
- Remonta o plugin do zero, reescreve o lock e valida
A aplicação remonta o plugin do zero com a seleção inteira do lock, em vez de editar a árvore montada. É mais lento e é de propósito: editar no lugar deixa arquivo órfão quando uma skill encolhe entre versões.
O que conta como modificação local
A comparação do disco contra os hashes do lock produz três listas — alterados, removidos e novos. A instalação só é considerada limpa quando as três estão vazias.
Um arquivo novo criado dentro da pasta de uma skill já bloqueia o update, mesmo
que nada tenha sido alterado. A mensagem do bloqueio lista os alterados e os removidos, mas não os novos —
então uma skill pode aparecer bloqueada com uma lista aparentemente vazia. Se isso acontecer, procure por
arquivo acrescentado à mão dentro de .expx/marketplace/plugins/expx/skills/<nome>/.
Rollback
Como o .expx/ é commitado, desfazer uma atualização é revertê-lo pelo versionador. O
update imprime isso em toda execução que aplica:
git checkout -- .expx
Não existe comando de desfazer no CLI, e é uma decisão: guardar a versão anterior dentro do
.expx/ duplicaria no repositório aquilo que o versionador já guarda melhor.
Referência do CLI
O que o doctor verifica
Dezesseis verificações, cada uma com severidade e correção sugerida. Achado de severidade
aviso não derruba a saída; erro sim.
npx expxdev doctor
| Verificação | Severidade | O que significa |
|---|---|---|
gitignore-ignora-expx | erro | o .gitignore ignora o .expx/, que precisa ser versionado |
sem-expx | erro | a pasta .expx/ não existe — o diagnóstico para aqui |
lock-ilegivel | erro | lock ausente, JSON inválido ou fora do formato — o diagnóstico para aqui |
lock-futuro | erro | o lock foi criado por uma versão mais nova do CLI |
plugin-json-invalido | erro | plugin.json ausente ou fora do schema |
marketplace-json-invalido | erro | marketplace.json ausente ou fora do schema |
skill-ausente | erro | skill do lock sem pasta em disco |
caminho-fora | erro | skill referencia caminho fora da própria pasta |
settings-ausente | erro | harness inclui claude e a configuração está ausente ou inválida |
plugin-nao-habilitado | erro | o plugin não está habilitado na configuração |
colisao-de-nome | erro | a mesma skill existe em .claude/skills/ e em .opencode/skills/ |
<skill>-sem-motor | erro | hook instalado sem a pasta de assets da skill ao lado |
modificacao-local | aviso | o disco divergiu do lock |
skill-nao-travada | aviso | a skill segue uma branch, não uma versão publicada |
rastro-fora-do-contrato | aviso | linhas do rastro fora do contrato expx-eventos |
rastro-chave-nao-declarada | aviso | chaves não declaradas no rastro |
Por que os achados do rastro são aviso. Um doctor que reprova a instalação por causa de linha antiga em disco é um doctor que as pessoas param de rodar. A instalação está correta; o histórico é que tem linhas de um contrato anterior.
[erro] a skill memox tem hook instalado mas nao tem o motor ao lado
correcao: rode expx init novamente para reinstalar a skill memox
[aviso] a skill sprintx nao esta travada em versao publicada
correcao: nenhuma acao necessaria; o repositorio ainda nao publica tag
Referência do CLI
O painel
Lê a pasta docs/, descobre os trabalhos gravados pelas skills e mostra no
navegador o que foi planejado, o que está em execução, o que travou e o histórico do que já foi entregue.
npx expxdev panel
Somente leitura, e não só por convenção. Qualquer requisição que não seja
GET recebe 405 com a mensagem o painel e somente leitura. O servidor
escuta exclusivamente em 127.0.0.1 — o host é constante no código, sem flag, opção ou variável
de ambiente que mude isso.
Porta já em uso não derruba o painel. O caso mais comum é o mais banal — um painel anterior ainda no ar na mesma porta. Em vez de um stack trace, o CLI diz qual porta está ocupada, oferece o endereço do painel que já está rodando e sugere uma porta livre.
Como ele lê o projeto
O que ele reconhece
O painel não varre todo .md do projeto: procura os nomes de arquivo do contrato.
A razão é que muitos .md legítimos não têm frontmatter — 00-LACUNAS.md e
00-AUDITORIA.md, por contrato, não levam — e varrer por extensão encheria a tela de “fora do
schema” com ruído.
Um trabalho é uma pasta com ORQUESTRADOR.md de frontmatter válido — a regra é sobre
o conteúdo, não sobre o caminho. Pasta sem orquestrador é ignorada em silêncio. O
00-INDICE.md só conta quando está dentro de uma pasta base/.
Violação e rejeição são coisas diferentes
A distinção importa e tem duas telas separadas:
O painel leu o arquivo, e o conteúdo desobedece uma regra do método. É um achado sobre o trabalho, e ele continua na tela com o defeito à vista.
O painel não conseguiu ler. É um achado sobre o arquivo, e ele fica de fora do painel até ser corrigido.
As dez regras de conformidade
| Violação | O que significa |
|---|---|
teste_ausente | task sem teste de integração ou funcional declarado |
concluida_sem_verde | task marcada como concluída sem a suíte verde |
paralela_com_dependencia | task declarada paralelizável mas com dependência aberta |
regressao_ausente | ocorrência do tipo bug sem o teste que reproduz |
sem_criterio_saida | fase ou sprint sem critério de saída |
bloqueio_antigo | bloqueio parado há mais dias que o limite configurado |
dependencia_inexistente | task que depende de um id que não existe neste trabalho |
ciclo_dependencia | duas ou mais tasks que se esperam em círculo |
estagio_incoerente | estágio declarado que não combina com a ferramenta (runx com f3, por exemplo) |
chave_omitida | chave obrigatória ausente do arquivo — pela regra R6, é violação, não rejeição |
Cada regra tem escopo estreito de propósito, porque violação falsa é pior que violação
ausente: regressão não é cobrada de trabalho da sprintx nem de ocorrência que não é
bug, e critério de saída não é exigido de fase que não o declara por não existir.
Os seis motivos de rejeição
A API
| Rota | Devolve |
|---|---|
GET /api/projeto | o estado inteiro do projeto |
GET /api/conformidade | as violações |
GET /api/rejeicoes | os arquivos que não puderam ser lidos |
GET /api/historico | as entregas já fechadas |
GET /api/memoria | o índice da memox, ou null — que é estado legítimo, não erro |
GET /api/saude | { ok, raiz, lido_em } |
GET /relatorio?oc=<id>&tipo=tecnico|uso | o relatório como página HTML autocontida |
GET /relatorio.md?oc=… | o mesmo relatório como download em Markdown |
WS /ws | o estado inteiro a cada mudança |
O websocket manda o estado inteiro, não um delta: o estado de um projeto documental é pequeno, e mandar tudo elimina a classe de bug em que servidor e tela discordam depois de uma mensagem perdida. Conexão caída fica visível na barra de status e reconecta sozinha — uma tela congelada mostrando dado velho é pior que um erro à mostra.
As telas
| Tela | O que mostra |
|---|---|
| Dashboard | seis cartões, quatro distribuições e os trabalhos recentes. A separação entre planejamento e execução vem do estágio, não do status |
| Trabalhos | tabela filtrável por ferramenta, tipo e status, ordenável por atualização, progresso ou título |
| Detalhe | sprint por sprint, fase por fase, task por task, com dependências, critérios de saída e caminho crítico |
| Conformidade | as violações agrupadas por tipo, com arquivo e linha |
| Histórico | as entregas, com link para os relatórios técnico e de uso |
| Memória | arquivos de risco, regressões, coincidências e artefatos contaminados |
| Fora do schema | as rejeições, em duas abas: erros de leitura e arquivos anteriores ao contrato |
Toda tela exporta CSV. Um filtro de período global — 7d, 30d, 90d,
mês, ano ou intervalo — recorta trabalhos, histórico, bloqueios e violações; data ausente nunca é filtrada
para fora.
Por que o quadro kanban foi removido
O kanban pressupõe cartões movendo-se entre colunas por decisão de pessoas. Aqui o estágio é a máquina de estados do método: ele avança quando um artefato passa a existir no disco, não quando alguém arrasta um cartão. A tabela conta essa verdade; o quadro contava outra.
A tela de Memória não respeita o filtro de período
Ao contrário das demais, e de propósito: o valor do sinal é justamente o antigo. Um arquivo que regrediu há dois anos continua sendo um arquivo que regride. Os arquivos de risco são ordenados por regressões, depois reprovações de QA, depois número de trabalhos — nunca por movimento, porque um arquivo central é tocado por dezenas de trabalhos sem nunca ter falhado, e ordenar por contagem o colocaria no topo, enterrando embaixo o arquivo que já quebrou duas vezes.
Referência do CLI
O watch
Acompanha um trabalho no terminal, ao vivo, sem sair do lugar onde você está trabalhando. Como o painel, ele nunca escreve nos arquivos do projeto.
2 bloqueios abertos
B-01 · T-02.03 · 3 dias · Falta o contrato do gateway de pagamento
B-02 · sem task · hoje · Ambiente de homologacao fora do ar
OC-2026-0142 · runx · Arredondamento na faixa de peso
e3 · 7/11 tasks · agora T-02.04
raio medio · arquivos 2/3 · linhas 31/80
fix/OC-2026-0142-arredondamento · pr aberto
[x] sprint-01 · Congelar o comportamento atual
[x] F-01.1 · Caracterizacao
[x] T-01.01 Teste de caracterizacao da faixa 0-5kg
[x] T-01.02 Teste de caracterizacao da faixa 5-30kg
[>] sprint-02 · Corrigir o arredondamento
[>] F-02.1 · Fix
[x] T-02.01 Teste de regressao que reproduz o bug
[x] T-02.02 Corrigir a funcao de arredondamento
[!] T-02.03 Integrar com o gateway ← T-02.02
[>] T-02.04 Atualizar o relatorio de fechamento <
[ ] T-02.05 Revisar a documentacao de uso ||
eventos recentes
14:32 task_concluida T-02.02 · suite verde, 14 testes
14:28 suite_executada T-02.02 · 14 passed
14:11 regra_violada T-02.02 escopo-da-task · arquivo fora do plano
ultimo evento há 3 min · 1 violacao em aviso
Uso
| Forma | O que faz |
|---|---|
expx watch | segue o trabalho atual, lido do .expx/estado.json |
expx watch <trabalho_id> | segue um trabalho específico |
expx watch --todos | lista os trabalhos abertos, um por linha, sem árvore |
expx watch --colunas 100 | largura fixa, útil para capturar saída |
Sai com Ctrl+C, devolvendo o terminal ao estado anterior — cursor restaurado inclusive em encerramento por exceção.
Como ele escolhe o trabalho
A precedência é deliberada, e cada degrau existe para um caso real:
- o id que você pediu na linha de comando
- o
trabalhodoestado.json, se ele existir no disco observado — apontar para uma pasta apagada ou de outro repositório não trava o watch - entre os trabalhos
em_andamento, o mais recente poratualizado_em - sem nenhum em andamento: o mais recente entre os abertos
- nada aberto: o mais recente entre todos, inclusive concluídos
Três gatilhos, três custos
O watch não relê tudo a cada mudança. Ele separa o que mudou:
| Mudou | O que ele relê |
|---|---|
qualquer arquivo em docs/ | a visão inteira — a única releitura cara |
.expx/estado.json | só o estado, e recalcula se está degradado |
docs/eventos/*.jsonl | só a cauda dos eventos e a contagem de violações |
O rastro é lido pela cauda — só os últimos 64 KB, em linhas completas, descartando o fragmento cortado ao meio. O arquivo só rotaciona em 5 MB, e reler tudo a cada evento seria a chamada cara que a especificação proíbe.
Modo degradado. Quando o .expx/estado.json não pode ser lido —
ausente, JSON inválido ou de uma versão desconhecida —, o watch continua funcionando a partir do plano.
O que some é o que só o estado sabe: raio, orçamento, branch e estado do PR.
O desenho
Bloqueio aberto sobe ao topo, acima até do cabeçalho. A ordem das seções é fixa: bloqueios, cabeçalho, árvore, eventos, rodapé.
A tela é redesenhada de forma incremental: as linhas anteriores são guardadas, comparadas, e só as que mudaram são reescritas. Se nada mudou, nada é escrito — por isso não pisca. O buffer alternativo do terminal foi descartado de propósito: ele apagaria o que estava na tela quando o watch sai.
| Marca | Task | Sprint e fase |
|---|---|---|
[x] | concluida | concluido |
[>] | em_andamento | em_andamento |
[!] | bloqueada | bloqueado |
[ ] | pendente | nao_iniciado |
São dois vocabulários porque os enums do contrato são mesmo diferentes para task e para grupo — e não
são intercambiáveis. Além das marcas, || indica task paralelizável, ← lista as
dependências e < aponta a task em foco.
Contratos
Convenções R1–R14
O documento raiz. Estas regras valem para todo artefato do método: frontmatter YAML, linha do rastro, configuração de hook, frontmatter de agente. Os contratos derivados não as repetem — citam por número.
| Regra | Detalhe | |
|---|---|---|
R1 | O bloco YAML é a primeira coisa do arquivo | Entre --- antes e depois. Nada acima: nem linha em branco, nem comentário, nem título. BOM é tolerado |
R2 | Toda chave em snake_case, minúscula, sem acento | modulo_afetado, nunca móduloAfetado nem modulo-afetado |
R3 | Todo valor de enum minúsculo e sem acento | concluida, nunca Concluída. Vale só para enum: texto livre leva acento normalmente |
R4 | Datas em ISO | AAAA-MM-DD; timestamp do rastro AAAA-MM-DDTHH:MM:SSZ, sempre UTC. Obtenha do sistema, nunca de memória |
R5 | Booleanos true/false, sem aspas | Nunca "true", sim, yes ou 1 |
R6 | Chave nunca omitida | Lista vazia é []. Valor ausente é null. A chave está sempre lá |
R7 | O frontmatter é a única fonte para a máquina | A prosa abaixo é para humano. Nenhum leitor extrai informação dela |
R8 | Campos de texto são de uma linha | Parágrafo vai na prosa; o YAML carrega só o resumo |
R9 | atualizado_em é reescrito a cada gravação | Mesmo que só um campo tenha mudado |
R10 | Nenhum caminho absoluto em nenhum valor | Caminho absoluto vaza o nome de usuário da máquina, quebra ao trocar de máquina e polui o diff |
R11 | Ausente é null, e só | Nada de n/a, -, "" ou nenhum. Em prosa, a marca é n/a por extenso |
R12 | Ids | Ver a tabela abaixo |
R13 | Idioma | Prosa em português do Brasil, com acento. Identificador em português sem acento, por R2 e R3 |
R14 | Encoding UTF-8, sem BOM | Não escreva BOM; leitores devem tolerá-lo na entrada |
Por que R6 existe. O painel diferencia “não se aplica” de “esqueceram de escrever”. Omitir a chave apaga essa diferença. E chave omitida é violação do método, não rejeição do arquivo: o arquivo continua sendo lido e aparece no painel com o defeito à vista. Rejeitar faria o trabalho sumir da tela justamente quando ele tem um problema — o oposto do que o painel serve para fazer.
R12 — os formatos de id
| Artefato | Formato | Exemplo |
|---|---|---|
| Task | T-NN.MM | T-01.02 |
| Fase | F-NN.M | F-01.1 |
| Sprint | sprint-NN | sprint-01 |
| Bloqueio | B-NN | B-01 |
| Decisão | D-NN | D-07 |
| Ocorrência | OC-AAAA-NNNN | OC-2026-0142 |
F-01 sozinho é forma antiga e não deve ser gerada.
R4 na prática
Modelo de linguagem não sabe que dia é hoje. Data escrita de memória é o erro mais comum e o mais silencioso do método:
date +%Y-%m-%d # data
date -u +%Y-%m-%dT%H:%M:%SZ # timestamp do rastro
Cite sempre com o prefixo R. Existe numeração histórica sem prefixo,
herdada da primeira versão do expx-schema, e ela não coincide com esta. Uma citação a
“regra 6”, sem R, é ambígua.
Contratos
expx-schema v1
O frontmatter YAML de todo arquivo de estado. As skills escrevem; o painel
lê e nunca escreve. É a fonte da verdade sobre os kind, seus campos e seus
enums quando skill e leitor divergirem.
O cabeçalho comum
Todo arquivo carrega estas quatro chaves antes das específicas:
---
expx_schema: 1
expx_tool: sprintx # sprintx | runx — quem escreveu
kind: tasks
trabalho_id: exportacao-csv-relatorios
---
trabalho_id é o slug da feature (sprintx) ou o ID da ocorrência (runx). É a chave que
costura tudo — um trabalho, um nome, do plano até a entrega. O único kind que não o
carrega é o relatorios_indice, que é do projeto inteiro e não de um trabalho.
Os treze kinds
| kind | Arquivo | Campos além do cabeçalho |
|---|---|---|
orquestrador | ORQUESTRADOR.md | titulo, tipo_trabalho, tipo_ocorrencia, estagio, status, criado_em, atualizado_em, concluido_em, sprints[], caminho_critico[] |
sprint | sprint-NN/sprint.md | sprint_id, titulo, status, criterio_saida, fases[], riscos[], atualizado_em |
fases | sprint-NN/fases.md | sprint_id, atualizado_em, fases[] de {id, titulo, status, criterio_saida, paralelizavel, paralela_com[], tasks[]} |
tasks | sprint-NN/tasks.md | sprint_id, atualizado_em, tasks[] — o arquivo mais importante para o painel |
bloqueios | BLOQUEIOS.md | atualizado_em, bloqueios[] de {id, task, aberto_em, resolvido_em, descricao} |
decisoes | 00-DECISOES.md | atualizado_em, decisoes[] de {id, decisao, alternativa_descartada, motivo, status, bloqueante} |
ocorrencia | 00-OCORRENCIA.md | titulo, tipo_ocorrencia, recebido_em, origem, tem_reproducao, modulo_afetado[] |
causa_raiz | 01-CAUSA-RAIZ.md | modo, comprovada, evidencia, arquivos_impactados[], decisoes[], atualizado_em |
qa | QA.md | veredito, executado_em, achados[] de {severidade, arquivo, problema, correcao_sugerida} |
base_indice | base/00-INDICE.md | atualizado_em, areas[] de {arquivo, titulo, lacunas} |
relatorio_tecnico | relatorios/…/tecnico.md | titulo, tipo_ocorrencia, fechado_em, modulo_afetado[], arquivos_alterados[], testes_adicionados |
relatorio_uso | relatorios/…/uso.md | o mesmo, sem arquivos_alterados nem testes_adicionados — é o arquivo do cliente, e não menciona código nem no YAML |
relatorios_indice | relatorios/INDICE.md | atualizado_em, entradas[] de {data, oc_id, tipo, modulo, resumo, pasta} — sem trabalho_id |
A anatomia de uma task
---
expx_schema: 1
expx_tool: runx
kind: tasks
trabalho_id: OC-2026-0142
sprint_id: sprint-01
atualizado_em: 2026-08-29
tasks:
- id: T-01.02
titulo: Corrigir o arredondamento na faixa de peso
fase: F-01.1
status: concluida
objetivo: Fazer o calculo usar duas casas em vez de truncar
arquivos:
cria: []
altera: [src/frete/calculo.ts]
teste_regressao: test/frete/calculo.regressao.test.ts
teste_integracao: test/frete/calculo.int.test.ts
teste_funcional: test/frete/cotacao.func.test.ts
criterio_aceite: O teste falha antes do fix e passa depois
depende_de: [T-01.01]
paralelizavel: false
concluida_em: 2026-08-29
suite: verde
---
O campo fase da task é o vínculo autoritativo entre task e fase — não a
lista tasks[] da fase. Quando as duas discordam, vale o que a task diz.
arquivos aceita duas formas: o mapa {cria, altera} que as duas skills gravam, e
a lista plana que o contrato descrevia. A lista plana é normalizada para o mapa na leitura.
Os enums
| Campo | Valores |
|---|---|
expx_tool | sprintx · runx |
tipo_trabalho | feature · ocorrencia |
tipo_ocorrencia | bug · melhoria-ui · melhoria-ux · novo-relatorio · regra-de-calculo · campo-novo · outro · null |
estagio | sprintx: f1…f6 · runx: e1…e5 |
status trabalho, sprint, fase | nao_iniciado · em_andamento · bloqueado · concluido |
status task | pendente · em_andamento · concluida · bloqueada |
suite | verde · vermelha · nao_executada |
veredito | aprovado · reprovado |
severidade | alta · media · baixa |
modo causa raiz | causa_raiz · analise_impacto |
evidencia | teste_falho · log · codigo · null |
status decisão | fechada · pendente |
Onde o painel procura
| Caminho | O quê |
|---|---|
docs/<slug>/ | features da sprintx |
docs/manutencao/<OC-ID>-<slug>/ | ocorrências da runx |
docs/relatorios/ | o histórico do que já foi entregue |
Contratos
expx-eventos v1
O rastro append-only, e o comportamento de hooks e agentes. O estado responde “onde está”; o rastro responde “o que aconteceu e quando”.
A linha do rastro
Uma linha JSON por evento, em docs/eventos/<trabalho_id>.jsonl. Escrito por hooks e
pelas skills nas transições de fase; ninguém edita à mão.
{"ts":"2026-08-29T14:32:10Z","expx_eventos":1,"trabalho_id":"OC-2026-0142",
"ferramenta":"runx","origem":"hook","evento":"task_concluida","fase":"e3",
"task":"T-01.02","agente":"principal","resultado":"ok",
"detalhe":"suite verde, 14 testes","arquivos":["src/frete/calculo.ts"]}
As doze chaves são obrigatórias, nesta ordem, e nenhuma é omitida — por R6, o que não se
aplica vai null, e arquivos vazio vai []:
Duas chaves extras são permitidas depois das doze: hook (o nome do hook que decidiu, quando
a origem é hook) e faixa (a faixa de atenção do arquivo tocado).
A validação é por contenção, nunca por igualdade de conjunto. O histórico explica: a verificação de uma skill passou a reprovar toda linha escrita por outras duas, porque elas acrescentavam uma chave extra legítima.
O vocabulário de eventos
| Evento | Quem grava |
|---|---|
fase_iniciada · fase_concluida | a skill |
task_iniciada · task_concluida · task_bloqueada | a skill |
suite_executada | hook PostToolUse |
arquivo_alterado | hook PostToolUse |
regra_violada | hook em modo aviso |
acao_bloqueada | hook em modo bloqueio |
agente_iniciado · agente_concluido | hook SubagentStop e a skill |
veredito_emitido | o agente auditor ou o QA |
commit_criado · pr_aberto | a mergex |
O campo agente nunca é null: quando não há subagente, o valor é
principal.
Como os hooks funcionam
| Claude Code | OpenCode | |
|---|---|---|
| Onde vivem | configuração do projeto, aninhados evento → matcher → handler | plugins JS auto-carregados de .opencode/plugin/ |
| Como bloqueiam | exit 2 em PreToolUse; o stderr volta ao modelo | lançar exceção em tool.execute.before |
| Modo aviso | o hook registra e deixa passar | não existe no before — o contorno é anexar no after, com prefixo dizendo que a ação NÃO foi bloqueada |
Canal em PostToolUse | só JSON no stdout: o exit 2 não bloqueia e o stderr não volta ao modelo | tool.execute.after |
As sete regras que todo hook obedece
- Rápido — acima de 200 ms o desenvolvedor sente
- Silencioso quando passa — hook que fala sempre vira ruído e é ignorado
- Falha aberta, exceto os de segurança
- Sem rede
- Mensagem acionável — dizer o que fazer, não só o que está errado
- Sem estado próprio — o disco já é o estado
- Sempre grava no rastro, inclusive quando permite
Versionamento e rotação
O rastro é ignorado pelo versionador por padrão. Acima de 5 MB o arquivo
vira <trabalho_id>.1.jsonl e um novo começa; os leitores leem os dois.
Uma consequência que não estava prevista: o rastro dá o esforço real por task sem
ninguém anotar nada, e é isso que calibra a estimativa da sprintx nas features seguintes.
Contratos
expx-estado v1
Um arquivo minúsculo em .expx/estado.json, lido pela barra de status e pelo
expx watch. Derivado e descartável: apagá-lo não pode quebrar nada.
A regra que justifica tudo. A barra roda a cada mensagem do assistente com
debounce de 300 ms, e se um gatilho novo dispara enquanto o script ainda executa, o harness
mata a execução em vez de enfileirar — script lento simplesmente não aparece. Por isso a barra
nunca lê tasks.md, frontmatter, plano ou rastro: só este arquivo.
Os quinze campos
{
"expx_estado": 1,
"atualizado_em": "2026-08-29T14:32:10Z",
"trabalho": "OC-2026-0142",
"ferramenta": "runx",
"titulo_curto": "Arredondamento na faixa",
"fase": "e3",
"task": "T-02.04",
"tasks_concluidas": 7,
"tasks_total": 11,
"raio": "medio",
"orcamento_arquivos": "2/3",
"orcamento_linhas": "31/80",
"branch": "fix/OC-2026-0142-arredondamento",
"pr_estado": "aberto",
"bloqueios": 2
}
Quem escreve o quê
Cada dono atualiza apenas os seus campos: ler, alterar o que é seu, gravar — nunca sobrescrever o arquivo inteiro.
| Campos | Dono |
|---|---|
trabalho, ferramenta, titulo_curto, fase | sprintx e runx, nas transições |
task, tasks_concluidas, tasks_total | sprintx e runx, ao abrir e fechar task |
raio, orcamento_arquivos, orcamento_linhas | legadox |
branch, pr_estado | mergex |
bloqueios | quem registrar bloqueio |
As sete regras
- Somente exibição — derivado e descartável; apagá-lo não pode quebrar nada
- Chave nunca omitida — o que não se aplica vai
null:raiofora do modo legado,pr_estadoantes do push - Escrita atômica — temporário mais
rename - Pequeno — abaixo de 1 KB, nada de listas
titulo_curtocabe em 30 caracteres — corte, não quebre linha- Sem trabalho aberto,
trabalho,faseetaskviramnulle o arquivo continua existindo - Enums iguais aos do
expx-schema—e3, nãoE3;alto, nãoALTO
A barra de status é mecanismo do Claude Code. O OpenCode tem o seu, com formato possivelmente diferente — isso é lacuna a verificar, não paridade garantida.
Interno
Arquitetura
Camadas isoladas, uma pasta por responsabilidade. Nenhuma regra de negócio vive no código de linha de comando.
src/
nucleo/ catálogo das skills, resolução de versão, busca, layout, lock, integridade
plugin/ montagem do plugin e dos manifestos, com escrita atômica
harness/ Claude Code e OpenCode, merge de configuração, backup
doctor/ os verificadores e o efeito de cada achado
update/ comparação com o lock, modificação local, compatibilidade de schema
parser/ leitura do expx-schema e do índice da memox, com falha aberta
servidor/ o painel: HTTP, websocket e o observador de arquivos
watch/ o watch: fontes, visão, desenho puro e terminal
cli/ roteamento de subcomando, flags e seleção interativa
ui/ a interface do painel (React + Vite)
docs/contrato/ os contratos compartilhados pelas oito skills
Padrões que atravessam o código
Escrita atômica em toda parte
O .expx/ é montado numa pasta temporária ao lado do destino e trocado por rename.
O .expx/estado.json segue a mesma regra. Nunca há um estado intermediário visível no disco.
Falha aberta onde a ausência é normal
A leitura do índice da memox devolve null em quatro casos, e nenhum deles é erro: arquivo
ausente (o índice é gitignorado — é o caso comum num clone novo), JSON inválido (o motor reescreve o arquivo
inteiro, e ler no instante da gravação devolve truncado), raiz que não é objeto, e versão desconhecida.
Degradar mostrando, nunca quebrar.
Dois observadores de arquivo, deliberadamente diferentes
| Painel | Watch | |
|---|---|---|
| Debounce | 300 ms | 150 ms |
.expx/ | ignorado | observado, com profundidade zero |
| Gatilhos | um só, cego | três: plano, estado e rastro |
O painel ignora o .expx/ porque é lá que a memox grava o índice: sem ignorá-lo, reindexar
dispararia o observador, que recarregaria o estado, que releria o índice — realimentação sem dado novo
nenhum. O watch, ao contrário, precisa do estado.json; e observa a pasta, não o
arquivo, porque a escrita atômica substitui o inode e um observador preso ao arquivo antigo pararia de ver
mudança depois da primeira.
O debounce não é conforto, é correção
As skills gravam tasks.md a cada transição de task. Ler no instante da gravação produz YAML
truncado — uma rejeição transitória que apareceria e sumiria da tela “fora do schema”, assustando sem motivo.
Frontmatter lido com posição de linha
O leitor de YAML foi escolhido por dar a linha de cada campo — é o que permite ao painel dizer onde está o problema. A biblioteca mais comum para frontmatter foi descartada por dois motivos medidos: não dá posição, e mantém um cache global indexado pelo conteúdo, de modo que a segunda leitura da mesma string com YAML inválido devolvia dados vazios em silêncio.
Cor ANSI escrita à mão
Os pacotes de cor presentes em node_modules são dependências transitivas de ferramentas de
desenvolvimento, e somem na instalação de produção. Seis papéis semânticos — sucesso, atenção, erro,
destaque, apagado e neutro — cobrem tudo o que o watch precisa.
Largura contada em code points, com normalização
Nome de arquivo vindo do macOS chega decomposto, e contar caracteres como o JavaScript conta por padrão erraria o corte em 80 colunas. A limitação conhecida: caractere de largura dupla conta como uma coluna — aceitável porque a especificação proíbe emoji e a prosa é em português.
Interno
Decisões de arquitetura
Este projeto foi planejado e executado com o próprio método. Estas são algumas das decisões
registradas, com a alternativa que foi descartada e o motivo — o formato do kind: decisoes.
| Decisão | Alternativa descartada | Motivo |
|---|---|---|
| O plugin fica dentro da árvore do marketplace | marketplace e plugin como irmãos, como a especificação descrevia | source relativo que sobe de diretório é rejeitado com source: Invalid input |
O init chama claude plugin marketplace add e install | apenas declarar o marketplace na configuração do projeto | cinco sintaxes testadas em execução e nenhuma carregou o plugin |
| Ler a lista de plugins habilitados como array ou objeto, e escrever objeto | seguir o array da documentação oficial | o arquivo real que o Claude Code escreve usa objeto |
Busca por git clone raso, com o git do sistema | API REST do GitHub com token | aproveita a credencial já configurada e não esbarra em limite de requisição |
Com OpenCode, as skills vão só para .claude/skills/ | copiar para os dois diretórios | dois name iguais são resolvidos por último-a-escrever-vence, em silêncio |
| Modificação local por hash SHA-256 de cada arquivo | hash único da árvore, ou comparação por data de modificação | hash por arquivo diz qual arquivo mudou; data de modificação muda sozinha |
| Rollback pelo versionador | guardar a versão anterior dentro do .expx/ | duplicaria no repositório o que o versionador já guarda melhor |
Normalizador que localiza o SKILL.md e toma a pasta dele como raiz | assumir caminho fixo por repositório | os repositórios reais divergem, e um layout novo passa a funcionar sem mexer no CLI |
Comandos do OpenCode sempre em commands/, no plural | espelhar a pasta de origem, que varia entre singular e plural | a forma documentada é o plural; a normalização acontece na escrita |
| Framework de linha de comando escrito à mão | adotar uma biblioteca de argumentos | nenhuma dependência nova para o que já estava resolvido no projeto |
Escrita atômica por pasta temporária e rename | escrever direto no destino final | falha no meio deixaria a instalação anterior destruída |
| O painel difunde o estado inteiro a cada mudança | enviar um delta | elimina a classe de bug em que servidor e tela discordam depois de uma mensagem perdida |
| Releitura total do disco a cada mudança | releitura incremental do arquivo que mudou | as regras cruzam referências entre arquivos; leitura parcial produziria violação falsa |
| Ordenar arquivos de risco por regressões | ordenar por número de trabalhos | arquivo central é tocado por dezenas de trabalhos sem nunca ter falhado |
| A tela de Memória ignora o filtro de período | aplicar o filtro global como nas demais | o valor do sinal é justamente o antigo |
| Varredura por nome exato, não por extensão | varrer todo .md | 00-LACUNAS.md e 00-AUDITORIA.md não levam frontmatter por contrato |
| Um trabalho é definido pelo conteúdo, não pelo caminho | exigir uma pasta em local fixo | a regra vale para qualquer estrutura de pastas que o time adote |
| Chave omitida é violação, não rejeição | rejeitar o arquivo inteiro | rejeitar faria o trabalho sumir da tela justamente quando ele tem um problema |
| Skill sem tag não vira aviso na instalação | avisar sempre que a skill não estiver travada | nenhum repositório publica tag hoje, e o aviso disparava sempre |
O doctor verifica o efeito da instalação, não só a sintaxe | validar apenas o JSON dos manifestos | arquivo sintaticamente válido e instalação quebrada são coisas diferentes |
O plano completo, a base de conhecimento e as decisões deste projeto vivem em
docs/expx-cli/, e a integração da memória em docs/memox-painel/.
Interno
Desenvolvimento
npm install
npm test # 441 testes em 92 arquivos, sem acesso à rede
npm run typecheck
npm run build
TypeScript estrito e ESM, Node ≥ 20.19, com o runner dividido em três projetos —
servidor, ui e cli. A suíte roda contra repositórios git locais
criados em tempo de teste: nenhum teste depende de rede nem do estado do GitHub.
Segurança e limites
- Nunca pede nem armazena credencial. Repositório privado usa a credencial de git já configurada na máquina
- Nunca escreve fora da raiz do projeto
- Nunca escreve uma skill. O CLI busca e empacota; jamais edita conteúdo de skill
- Escrita atômica. Se falhar no meio, o
.expx/anterior permanece intacto - O painel e o watch são somente leitura, e o painel escuta apenas em
127.0.0.1 - Toda escrita destrutiva pede confirmação, com flag para pular em ambiente não interativo
Divergências conhecidas entre código e contrato
Registradas aqui porque quem for implementar um leitor precisa saber:
| Ponto | Situação |
|---|---|
O kind: decisoes | existe no código e nas skills, mas não está descrito no contrato expx-schema v1 |
Os kind da prodx | a skill grava produto, pedido, veredito e briefing, mas o contrato não os descreve — o parser rejeita kind desconhecido, então os artefatos dela ainda não aparecem no painel |
| A regra R8 (texto de uma linha) | tem validador escrito, mas ele não está aplicado a nenhum campo |
A violação chave_omitida | não tem rótulo em português na tela de Conformidade, e aparece pelo identificador |
O CONTRATO-expx-estado.md | numera as regras de 1 a 7, sem o prefixo R que as convenções exigem |
| A verificação de compatibilidade de schema | está implementada, mas não está ligada ao fluxo do init nem do update |
Licença
MIT.