/spike — recorte → isola → mocka → testa → muda → aprova → propaga
Por que existe
Mudança transversal (trocar padrão, migrar API, refatorar util usado em 40 lugares) tem dois
modos de falha: (a) aplicar direto e quebrar o projeto em pontos não previstos; (b) planejar
no abstrato e descobrir na implementação que a abordagem não fecha. O spike mata os dois:
prova a abordagem em uma fatia pequena, com testes, e só então escala.
Regra de ouro: nada toca o projeto real antes do gate 5. Até lá, todo trabalho vive em
.spike/<slug>/ (gitignored) ou em worktree dedicado.
Uso
/spike <ref> # ref = caminho:linhas, símbolo, ou descrição da seção
/spike <ref> -- <mudança> # já com a mudança pretendida descrita
/spike --resume <slug> # retoma spike existente em .spike/<slug>/
/spike --propagate <slug> # pula direto para a fase 6 (spike já aprovado)
Fases (executar em ordem; cada gate exige o output indicado antes de avançar)
1. Analisar a seção referenciada
- Resolver
<ref> para arquivo(s) + intervalo de linhas concreto. Se ambíguo, listar candidatos
e perguntar — não adivinhar.
- Mapear a fronteira da fatia: o que ela importa, o que a importa, side effects
(I/O, rede, banco, env, relógio, aleatoriedade), estado global tocado.
- Contar os pontos de propagação: quantos outros lugares do projeto usam o mesmo padrão
e precisariam da mesma mudança. Isso define o tamanho da fase 6.
- Se
graphify-out/ existir no repo, usar /graphify como primeira fonte para o mapa de
dependências (é local, só AST — permitido pelo guardrail).
Gate 1 → imprimir um bloco ## Fatia com: arquivos/linhas, dependências de entrada,
dependentes, side effects, N pontos de propagação, e a mudança pretendida em 1 frase.
2. Clonar a fatia para o sandbox
- Criar
.spike/<slug>/ na raiz do repo (slug = kebab-case curto da mudança). Adicionar
.spike/ ao .gitignore se ainda não estiver; não commitar o sandbox nunca.
- Copiar só os arquivos da fatia + o mínimo de tipos/helpers que ela precisa para compilar.
Preferir cópia literal a reescrita: o objetivo é reproduzir o comportamento atual, não
melhorá-lo ainda.
- Registrar em
.spike/<slug>/MANIFEST.md a origem de cada arquivo copiado
(caminho-original → caminho-no-sandbox). Isso é o mapa de volta para a fase 6.
3. Isolar e mockar
- Para cada dependência externa listada no gate 1, escolher uma estratégia e anotar no
MANIFEST:
- stub — retorno fixo (para I/O, rede, banco, tempo);
- fake — implementação em memória com comportamento real (para repositórios, caches);
- real — manter a dependência quando for pura e barata (utils, tipos).
- Nunca mockar a própria coisa que está sendo mudada. Mock é para a fronteira, não para o
alvo.
- Usar o test runner que o projeto já tem (vitest/jest/pytest/etc.). Não introduzir runner novo
só para o spike.
- Se a fatia envolve UI, o "mockup" é uma story/fixture renderizável — não screenshot manual.
Validar com
/browse em sessão própria (-s=spike-<slug>): snapshot mostra o esperado e
console sem erro. Isso entra no gate 2.
Gate 2 → a fatia clonada compila/importa no sandbox com as dependências mockadas, sem
tocar em nada fora de .spike/. Mostrar o comando que provou isso e sua saída resumida.
4. Testes de caracterização (comportamento ATUAL)
- Antes de mudar qualquer coisa, escrever testes que fixam o que a fatia faz hoje,
incluindo comportamento estranho/bugado que exista — o objetivo é detectar regressão, não
julgar.
- Cobrir: caminho feliz, bordas conhecidas, e pelo menos um caso por side effect mockado.
- Rodar. Tudo verde. Se algo não passa contra o código original copiado, o mock está errado —
corrigir o mock, não o teste.
Gate 3 → suite verde contra o código original. Imprimir contagem de testes e o comando.
5. Implementar a mudança na fatia
- Aplicar a mudança dentro do sandbox, arquivo por arquivo do MANIFEST.
- Rodar os testes de caracterização. Para cada teste que quebrar, classificar explicitamente:
- regressão → corrigir a implementação;
- mudança intencional de comportamento → atualizar o teste E anotar no MANIFEST em
## Comportamentos alterados (essa lista vai para o usuário no gate 5).
- Adicionar testes novos para o comportamento novo, se houver.
- Produzir o diff da fatia:
diff -ru entre a cópia original (guardar em
.spike/<slug>/before/) e a versão mudada (.spike/<slug>/after/).
Gate 4 → suite verde na versão mudada. Imprimir: testes passando, diff resumido
(arquivos + linhas +/-), e a lista ## Comportamentos alterados.
6. Aprovação — PARAR AQUI
Apresentar ao usuário, nesta ordem, sem pedir permissão implícita:
- O diff da fatia (completo se < 150 linhas; senão, por arquivo com resumo).
## Comportamentos alterados — vazio se refatoração pura.
- Os N pontos de propagação do gate 1, agrupados por padrão de mudança (ex.: "12 arquivos
trocam
parseFloat(x.replace(',', '.')) por parseBRL(x)").
- Riscos que o sandbox não cobre (integração real, migrations, dados de prod, i18n…).
- Estimativa honesta do tamanho da fase 7, sinalizada como estimativa.
Usar AskUserQuestion com opções: Aprovar e propagar / Ajustar o spike / Descartar.
Não avançar sem resposta. "Parece bom" em texto livre conta como aprovar; silêncio não.
Gate 5 → aprovação explícita registrada.
7. Propagar para o projeto
- Entrar em worktree (
EnterWorktree) se ainda não estiver em um — o .spike/ original fica
no checkout de origem e continua servindo de referência.
- Aplicar a mudança aos pontos de propagação em lotes pelo agrupamento do gate 5. Após
cada lote: build + testes do projeto e, se há telas afetadas, smoke test via
/browse
(snapshot + console limpo). Se um lote quebra — teste ou visual —, parar, reportar, não
seguir para o próximo.
- Levar os testes de caracterização do sandbox para o local canônico de testes do projeto
(adaptando imports) — eles são o legado útil do spike.
- Ao final: suite completa do projeto verde,
git diff --stat, commit por lote ou único
conforme o padrão do repo. Mencionar o slug do spike na mensagem de commit.
- Sugerir remover
.spike/<slug>/ só depois do merge; não apagar automaticamente.
Gate 6 → relatório: arquivos alterados, testes antes/depois, o que ficou fora e por quê.
Regras que não se negociam
- Fases 1–5 nunca editam arquivos fora de
.spike/. Se a tentação for "só ajustar esse
import no original", é sinal de que a fatia foi mal cortada — volte ao gate 1.
- Não pular a fase 4. Sem caracterização, o gate 4 não prova nada.
- Sandbox não vai para o git. Se
.spike/ aparecer em git status, corrigir o .gitignore
antes de qualquer commit.
- Se o projeto tiver worktrees paralelos (
git worktree list), checar se já existe um spike
ou branch para a mesma mudança antes de começar — não duplicar trabalho.
- Estimativas de esforço e de risco são estimativas; dizer isso.
Anti-padrões que este fluxo evita
| Tentação |
Por que o spike bloqueia |
| "Vou aplicar em tudo e rodar os testes" |
Testes do projeto raramente cobrem a fronteira exata da mudança; o spike cria essa cobertura primeiro |
| "Refatoro a fatia enquanto clono" |
Mistura mudança com cópia e você perde o baseline do gate 3 |
| "Mocko o alvo porque é complicado" |
Mock do alvo testa o mock, não o código |
| "Aprovação implícita — o usuário mandou fazer" |
O gate 5 existe para o usuário ver o diff antes de 40 arquivos mudarem |
1---2name: spike3description: Valida uma mudança em recorte isolado antes de aplicar ao projeto inteiro. Analisa a seção de código referenciada, clona só a fatia coberta para um sandbox, mocka as dependências externas, escreve testes de caracterização, implementa a mudança na fatia, e SÓ após aprovação explícita do usuário propaga a conversão para o projeto. Use quando o pedido for "testar essa abordagem antes", "refatorar X mas quero ver funcionando isolado primeiro", "migrar padrão Y em todo o projeto", "trocar lib/API em N lugares", ou qualquer mudança transversal/arriscada. NÃO use para bug fix pontual de 1 arquivo — vá direto.4---56# /spike — recorte → isola → mocka → testa → muda → aprova → propaga78## Por que existe910Mudança transversal (trocar padrão, migrar API, refatorar util usado em 40 lugares) tem dois11modos de falha: (a) aplicar direto e quebrar o projeto em pontos não previstos; (b) planejar12no abstrato e descobrir na implementação que a abordagem não fecha. O spike mata os dois:13prova a abordagem em uma fatia pequena, com testes, e só então escala.1415Regra de ouro: **nada toca o projeto real antes do gate 5.** Até lá, todo trabalho vive em16`.spike/<slug>/` (gitignored) ou em worktree dedicado.1718## Uso1920```21/spike <ref> # ref = caminho:linhas, símbolo, ou descrição da seção22/spike <ref> -- <mudança> # já com a mudança pretendida descrita23/spike --resume <slug> # retoma spike existente em .spike/<slug>/24/spike --propagate <slug> # pula direto para a fase 6 (spike já aprovado)25```2627## Fases (executar em ordem; cada gate exige o output indicado antes de avançar)2829### 1. Analisar a seção referenciada3031- Resolver `<ref>` para arquivo(s) + intervalo de linhas concreto. Se ambíguo, listar candidatos32 e perguntar — não adivinhar.33- Mapear a **fronteira** da fatia: o que ela importa, o que a importa, side effects34 (I/O, rede, banco, env, relógio, aleatoriedade), estado global tocado.35- Contar os **pontos de propagação**: quantos outros lugares do projeto usam o mesmo padrão36 e precisariam da mesma mudança. Isso define o tamanho da fase 6.37- Se `graphify-out/` existir no repo, usar `/graphify` como primeira fonte para o mapa de38 dependências (é local, só AST — permitido pelo guardrail).3940**Gate 1 →** imprimir um bloco `## Fatia` com: arquivos/linhas, dependências de entrada,41dependentes, side effects, N pontos de propagação, e a mudança pretendida em 1 frase.4243### 2. Clonar a fatia para o sandbox4445- Criar `.spike/<slug>/` na raiz do repo (slug = kebab-case curto da mudança). Adicionar46 `.spike/` ao `.gitignore` se ainda não estiver; **não commitar o sandbox nunca**.47- Copiar **só** os arquivos da fatia + o mínimo de tipos/helpers que ela precisa para compilar.48 Preferir cópia literal a reescrita: o objetivo é reproduzir o comportamento atual, não49 melhorá-lo ainda.50- Registrar em `.spike/<slug>/MANIFEST.md` a origem de cada arquivo copiado51 (`caminho-original → caminho-no-sandbox`). Isso é o mapa de volta para a fase 6.5253### 3. Isolar e mockar5455- Para cada dependência externa listada no gate 1, escolher **uma** estratégia e anotar no56 MANIFEST:57 - **stub** — retorno fixo (para I/O, rede, banco, tempo);58 - **fake** — implementação em memória com comportamento real (para repositórios, caches);59 - **real** — manter a dependência quando for pura e barata (utils, tipos).60- Nunca mockar a própria coisa que está sendo mudada. Mock é para a fronteira, não para o61 alvo.62- Usar o test runner que o projeto já tem (vitest/jest/pytest/etc.). Não introduzir runner novo63 só para o spike.64- Se a fatia envolve UI, o "mockup" é uma story/fixture renderizável — não screenshot manual.65 Validar com `/browse` em sessão própria (`-s=spike-<slug>`): snapshot mostra o esperado e66 `console` sem erro. Isso entra no gate 2.6768**Gate 2 →** a fatia clonada **compila/importa** no sandbox com as dependências mockadas, sem69tocar em nada fora de `.spike/`. Mostrar o comando que provou isso e sua saída resumida.7071### 4. Testes de caracterização (comportamento ATUAL)7273- Antes de mudar qualquer coisa, escrever testes que fixam o que a fatia faz **hoje**,74 incluindo comportamento estranho/bugado que exista — o objetivo é detectar regressão, não75 julgar.76- Cobrir: caminho feliz, bordas conhecidas, e pelo menos um caso por side effect mockado.77- Rodar. Tudo verde. Se algo não passa contra o código original copiado, o mock está errado —78 corrigir o mock, não o teste.7980**Gate 3 →** suite verde contra o código original. Imprimir contagem de testes e o comando.8182### 5. Implementar a mudança na fatia8384- Aplicar a mudança **dentro do sandbox**, arquivo por arquivo do MANIFEST.85- Rodar os testes de caracterização. Para cada teste que quebrar, classificar explicitamente:86 - **regressão** → corrigir a implementação;87 - **mudança intencional de comportamento** → atualizar o teste E anotar no MANIFEST em88 `## Comportamentos alterados` (essa lista vai para o usuário no gate 5).89- Adicionar testes novos para o comportamento novo, se houver.90- Produzir o **diff da fatia**: `diff -ru` entre a cópia original (guardar em91 `.spike/<slug>/before/`) e a versão mudada (`.spike/<slug>/after/`).9293**Gate 4 →** suite verde na versão mudada. Imprimir: testes passando, diff resumido94(arquivos + linhas +/-), e a lista `## Comportamentos alterados`.9596### 6. Aprovação — PARAR AQUI9798Apresentar ao usuário, nesta ordem, sem pedir permissão implícita:991001. O diff da fatia (completo se < 150 linhas; senão, por arquivo com resumo).1012. `## Comportamentos alterados` — vazio se refatoração pura.1023. Os **N pontos de propagação** do gate 1, agrupados por padrão de mudança (ex.: "12 arquivos103 trocam `parseFloat(x.replace(',', '.'))` por `parseBRL(x)`").1044. Riscos que o sandbox **não** cobre (integração real, migrations, dados de prod, i18n…).1055. Estimativa honesta do tamanho da fase 7, sinalizada como estimativa.106107Usar `AskUserQuestion` com opções: **Aprovar e propagar** / **Ajustar o spike** / **Descartar**.108Não avançar sem resposta. "Parece bom" em texto livre conta como aprovar; silêncio não.109110**Gate 5 →** aprovação explícita registrada.111112### 7. Propagar para o projeto113114- Entrar em worktree (`EnterWorktree`) se ainda não estiver em um — o `.spike/` original fica115 no checkout de origem e continua servindo de referência.116- Aplicar a mudança aos pontos de propagação **em lotes** pelo agrupamento do gate 5. Após117 cada lote: build + testes do projeto e, se há telas afetadas, smoke test via `/browse`118 (snapshot + console limpo). Se um lote quebra — teste ou visual —, parar, reportar, não119 seguir para o próximo.120- Levar os testes de caracterização do sandbox para o local canônico de testes do projeto121 (adaptando imports) — eles são o legado útil do spike.122- Ao final: suite completa do projeto verde, `git diff --stat`, commit por lote ou único123 conforme o padrão do repo. Mencionar o slug do spike na mensagem de commit.124- Sugerir remover `.spike/<slug>/` só depois do merge; não apagar automaticamente.125126**Gate 6 →** relatório: arquivos alterados, testes antes/depois, o que ficou fora e por quê.127128## Regras que não se negociam129130- Fases 1–5 **nunca** editam arquivos fora de `.spike/`. Se a tentação for "só ajustar esse131 import no original", é sinal de que a fatia foi mal cortada — volte ao gate 1.132- Não pular a fase 4. Sem caracterização, o gate 4 não prova nada.133- Sandbox não vai para o git. Se `.spike/` aparecer em `git status`, corrigir o `.gitignore`134 antes de qualquer commit.135- Se o projeto tiver worktrees paralelos (`git worktree list`), checar se já existe um spike136 ou branch para a mesma mudança antes de começar — não duplicar trabalho.137- Estimativas de esforço e de risco são estimativas; dizer isso.138139## Anti-padrões que este fluxo evita140141| Tentação | Por que o spike bloqueia |142|---|---|143| "Vou aplicar em tudo e rodar os testes" | Testes do projeto raramente cobrem a fronteira exata da mudança; o spike cria essa cobertura primeiro |144| "Refatoro a fatia enquanto clono" | Mistura mudança com cópia e você perde o baseline do gate 3 |145| "Mocko o alvo porque é complicado" | Mock do alvo testa o mock, não o código |146| "Aprovação implícita — o usuário mandou fazer" | O gate 5 existe para o usuário ver o diff **antes** de 40 arquivos mudarem |