todo (core)
O repositório é uma máquina de estado de circuito fechado construída a partir de arquivos que já existem. Nada mais armazena estado.
| Camada | Arquivo(s) | Função | Política de gravação |
|---|---|---|---|
| Requisitos | README.md, docs/*.md | Verdade absoluta: contratos, especificações, configuração, planos longos | Principalmente leitura. Editado sob "Desvio de documentação" em todo-continue; documentos de plano (docs/plans/) por todo-init/todo-plan/todo-add/todo-update; a linha Tests: do README por todo-init em caso afirmativo; o RTM opcional (reference/rtm.md) por todo-plan/todo-add/todo-continue apenas quando já existe; docs/status.html por todo-report |
| Fila ativa | TODO.md | Uma árvore de tarefas. Um rastreador de itens de trabalho, não um local para design | Editado apenas pelas habilidades todo-* |
| Validação | Código-fonte + conjuntos de teste | Verdade absoluta para "pronto" | Alterado apenas para a tarefa em questão |
| Arquivo | CHANGELOG.md | Permanente, somente anexação (Keep a Changelog + Conventional Commits) | Apenas ## [Unreleased] (no lançamento: renomeado para a versão, um novo vazio acima dele e as linhas de link no final) é tocado, por um drain raiz e o /todo-release confirmado; todo-init cria o arquivo ou adiciona um [Unreleased] ausente |
| Verificações (opcional) | .todo/check.sh, .todo/todo-lint.sh, job de CI | Lint + testes, executados por CI, um hook pré-push e /todo-continue | check.sh escrito por /todo-init --ci em caso afirmativo; todo-lint.sh copiado pelo usuário; comprometido pelo usuário |
| Armazenamento de versão | git | Branch ou worktree por tarefa. Nada chega à branch base não verificado | Veja "Modo Git" |
Prefira ferramentas de arquivo nativas (Read/Edit/Write) para edições de arquivo; no entanto, você editar, altere apenas as linhas pretendidas e mantenha a nova linha final do arquivo. Use o shell apenas para comandos git, teste e Done when, os scripts opcionais e os comandos de arquivo que uma skill nomeia (cp, chmod, mkdir -p, date, grep, cmp, mv e rm do próprio arquivo temporário de uma skill).
Arquivos de backlog são TODO.md, CHANGELOG.md, docs/plans/PROJECT.md, docs/plans/<ROOT-ID>-*.md nomeados por um Ref:, e as linhas Tests: e Base: do README escritas por uma skill todo-*. README.md é preparado por um commit de backlog apenas enquanto git diff README.md adiciona exatamente essas linhas, opcionalmente após uma linha em branco; edições do README que um nó faz sob "Desvio de documentação" são arquivos desse nó e são comprometidos com ele; qualquer outra alteração no README é do usuário: conta para a verificação de árvore limpa e nunca é preparada por um commit de backlog. As edições do backlog permanecem não comprometidas até o próximo commit que uma skill faz em uma branch todo/ (a reivindicação de árvore, geralmente), que as prepara por caminho explícito. Novas raízes, e qualquer alteração em um nó de uma árvore não reivindicada, são feitas apenas na branch base; em uma branch todo/ as skills recusam e nomeiam a base. A verificação de árvore limpa (reference/git-flow.md) as ignora.
Uso direto
/todo sozinho é somente leitura: listar os comandos, executar a verificação de invariante em TODO.md se existir, relatar. Não altera nada.
| Comando | Propósito |
|---|---|
/todo-init | Inicializar arquivos, detectar comando de teste e git, pré-planejamento opcional e configuração de CI, migrar o formato antigo |
/todo-plan | Planejar o trabalho em pistas e uma árvore; revisar o plano a qualquer momento |
/todo-add | Adicionar uma tarefa ou dividir uma solicitação em uma árvore |
/todo-continue | Executar o próximo nó de tarefa, verificá-lo, mesclá-lo em seu pai |
/todo-update | Alterações manuais de estado e campo |
/todo-status | Árvore somente leitura, pistas, histórico e pesquisa |
/todo-report | Escrever uma página de status HTML interativa para docs/status.html |
/todo-release | Transformar [Unreleased] em uma versão após o usuário confirmar |
Cada skill executa apenas seu próprio comando e nunca encadeia em outro sem solicitação.
Modo Git
No início de cada comando, execute git rev-parse --is-inside-work-tree.
- Repositório Git: cada nó trabalha em sua própria branch ou worktree (
reference/git-flow.md). A branch base é aquela que o usuário nomeia, caso contrário a linhaBase:do README, caso contrário a primeira que existir demain,master,trunk,develop; com nenhuma delas, pergunte uma vez. Quando o usuário nomeia uma base diferente do padrão, ofereça para adicionarBase: <branch>ao README (escrito em caso afirmativo; um arquivo de backlog como a linhaTests:). Cada etapa que faz checkout ou mescla na base (reivindicação de árvore, liberação de reivindicação, mesclagem base, lançamento) é executada no checkout principal (a primeira entrada degit worktree list): a partir de um worktree vinculado,cdpara lá primeiro; se estiver em outra branch com alterações, pare e imprima os comandos. - Não é um repositório git: avise uma vez por comando: "Este não é um repositório git. As habilidades todo ainda funcionam, mas sem branches, worktrees, commits ou mesclagens, portanto não há isolamento nem histórico. Execute
git initpara ativá-los." Em seguida, use o modo sem git: pule cada etapa do git, rastreie o progresso emState:(incluindofiles:tocados), ainda atualize marcadores e faça drain para CHANGELOG.md. A verificação permanece inalterada.
Nunca crie tag, force-push, hard reset ou clean. A única exclusão forçada de branch é de uma branch que contém apenas o próprio commit de reivindicação não publicado da skill (reference/git-flow.md, etapas 2 e 5 de reivindicação de árvore). Os comandos git das próprias skills nunca tocam na rede: sem fetch, pull ou push. Compartilhar commits é trabalho do git e seu. Um comando de teste pode baixar dependências; se falhar por falta de rede, bloqueie com esse motivo em vez de tentar novamente.
Esquema do TODO.md
# Active Backlog
## 🌳 Task Tree
Exatamente este cabeçalho e uma seção. Sem seções Em Andamento, Pronto ou Bloqueado: o marcador em cada tarefa é seu estado. Uma árvore vazia são os dois cabeçalhos e nenhuma tarefa.
Uma tarefa tem 2 a 4 linhas: o que fazer, como é validada, links opcionais e estado.
- [ ] **FEAT-002** · P1 · mid · XL · Adicionar refresh de token ao serviço de auth
- Done when: token antigo rejeitado após refresh; `npx jest tests/auth`; regressão: `npm test`
- Links: Ref: docs/auth.md#refresh · Depends: TASK-001 · From: FIX-001
- State: branch todo/FEAT-002-add-token-refresh-auth de main; next: build children
- [ ] **FEAT-002.1** · mid · Endpoint de refresh
- Done when: endpoint coberto por um teste de integração; `npx jest tests/auth/refresh.test.ts`
- [/] **FEAT-002.1.1** · high · Interface de armazenamento de token
- Done when: armazenamento faz round-trip de um token; `npx jest tests/auth/store.test.ts`
- State: tentativas 1/3; baseline 42 passando; branch todo/FEAT-002.1.1-token-store-interface de todo/FEAT-002.1-refresh-endpoint; next: build
| Parte | Regra |
|---|---|
| Cabeçalho | - [m] **ID** · [P0-P2, apenas raízes ·] COMPLEXIDADE [· TAMANHO] · o que fazer, uma frase: complexidade low, mid ou high (obrigatório); tamanho S, M, L ou XL (opcional) |
Done when: | Obrigatório. Critérios, depois ; e pelo menos um comando exato entre crases. Opcional ; regression: \cmd``; sem ele, a regressão é a suíte completa do projeto |
Links: | Opcional. Ref: <caminho#ancora>, Depends: <IDs>, From: <ID>, Lane: <nome> (apenas raízes), separados por · |
State: | Opcional, sobrevive a uma redefinição de contexto. Itens separados por ; , cada um no máximo uma vez, nesta ordem: attempts n/3, baseline <n> passing (ou none, ou red: <ids de teste com falha, separados por vírgula>), `tier: <low |
Blocked: | Em tarefas [!], em vez de State e em seu lugar (a última linha de campo): <motivo> → <comando entre crases> <erro, no máximo 5 linhas unidas com " / "> → <ação necessária>. Um bloqueio manual escreve n/a (manual) no meio |
Apenas esses quatro campos existem; uma tarefa nunca tem State e Blocked ao mesmo tempo. Mais de 4 linhas é prosa de design e pertence a docs/ (link com Ref:). Se uma tarefa precisar de mais, divida-a.
Marcadores: [ ] aberto, [/] ativo (no máximo um no arquivo), [!] bloqueado, [x] verificado e mesclado (ou sendo mesclado) em seu pai, aguardando sua raiz fazer drain.
Árvore, níveis e complexidade
Um nó no nível L tem seu cabeçalho indentado 2L espaços e seus campos 2L+2. Máximo de 3 níveis.
Regra de escopo. Cada folha é uma alteração que cabe em uma janela de contexto e toca no máximo 5 arquivos; trabalho maior é dividido em filhos (/todo-add). Um nó grande demais para ser dividido ainda mantém State: next: decompose até /todo-continue detalhá-lo.
Tamanho (opcional, após a complexidade) registra o escopo quando ajuda um leitor; quando presente, deve corresponder à árvore, e adicionar ou remover um nó atualiza o tamanho de cada ancestral:
| Tamanho | Significado | Onde |
|---|---|---|
S | Uma alteração, no máximo 2 arquivos | Folha |
M | Uma janela de contexto, no máximo 5 arquivos | Folha |
L | Tem filhos, todas folhas | Pai |
XL | Tem netos | Pai |
Uma folha com State: next: decompose pode carregar L/XL.
Complexidade diz quão difícil é o raciocínio, não quão grande é a alteração, para que um agente possa escolher um modelo adequado:
| Complexidade | Significado | Exemplos |
|---|---|---|
low | Mecânico: a causa e a alteração já são conhecidas, sem investigação | renomear, docs, config, uma guarda ou função pequena cuja correção a linha da tarefa declara |
mid | Trabalho comum que precisa de alguma investigação ou design (o padrão) | um novo endpoint, um bug cuja causa deve ser encontrada |
high | Raciocínio difícil ou alto risco | concorrência, segurança, migração de dados, especificação pouco clara, design entre módulos, algoritmos complicados |
Um pai é classificado por sua etapa de integração sozinha (geralmente low ou mid); seus filhos carregam seus próprios níveis. Raízes carregam a prioridade e a pista; filhos herdam ambos.
Roteamento de modelo (opcional)
Um projeto mapeia níveis para modelos com uma linha do README, por exemplo Models: low=haiku, mid=sonnet, high=opus (quaisquer nomes que o agente entenda). Sem essa linha, ou sem uma ferramenta de subagente, a complexidade é apenas uma dica e o trabalho é executado no modelo atual. Com ambos:
/todo-continue --delegatee execuções de pista dão a cada nó (ou raiz de pista, em sua complexidade mais alta) um subagente no modelo mapeado.- O revisor executa no nível do nó ou superior.
- Escalação: após uma tentativa de verificação com falha, a próxima tentativa executa um nível acima (
low→mid→high), registrado emState:comotier:. Um rótulolowerrado custa uma tentativa barata, não um nó bloqueado.
IDs
- Raízes
<PREFIXO>-<NNN>, uma sequência global, 3 dígitos. Filhos anexam.n:FEAT-002.1,FEAT-002.1.2. Pontos igualam o nível. - IDs nunca são reutilizados. Próximo número de raiz = maior número FEAT-/FIX-/TASK- encontrado em
TODO.md,CHANGELOG.md(incluindo IDs apósIncludes:),docs/plans/*.mde, no modo git, assuntos de commit (git log --all --format=%s, que nomeiam IDs descartados), mais 1. Próximo número de filho = maior número de filho sob esse pai encontrado nos mesmos lugares, mais 1.
| Prefixo | Significado | Cabeçalho CHANGELOG | Tipo de commit |
|---|---|---|---|
FEAT | Nova capacidade | ### Added | feat |
FIX | Bug ou regressão | ### Fixed | fix |
TASK | Refatoração, tarefa, docs, teste, perf, build | ### Changed | o que couber |
Filhos usam o prefixo de sua raiz.
Qual nó é o próximo
Um nó é trabalhável quando: é [ ]; todo filho é [x]; todo ID Depends: é satisfeito (em CHANGELOG.md como um ID de entrada ou após Includes:, também em git show <base>:CHANGELOG.md no modo git, ou [x] em TODO.md; quando apenas o CHANGELOG da base o satisfaz, /todo-continue mescla a base na branch da qual o nó começará antes de iniciá-lo, etapa 3; comandos somente leitura relatam "aguarda uma mesclagem base"); nenhum ancestral é [!]; e, no modo git, sua raiz não é reivindicada por outra branch. Uma raiz é reivindicada quando seu State: no TODO.md da branch base (git show <base>:TODO.md) nomeia uma branch; sua árvore é trabalhável apenas a partir de uma branch dessa família (todo/<ROOT-ID>-… ou todo/<ROOT-ID>.…). Uma árvore reivindicada ignorada é relatada como reivindicada por <branch>; quando essa branch existe neste clone, adicione "se este é seu trabalho: git switch <branch> (ou cd para seu worktree) e execute novamente para retomar". Uma branch neste clone pode pertencer a outra sessão, portanto nunca é retomada da base automaticamente. Se os arquivos de backlog tiverem edições não comprometidas na base, git switch para essa branch falha: diga isso e ofereça git stash push -- <caminhos do backlog> primeiro e git stash pop de volta na base.
Trabalho interrompido vem primeiro (modo git). Em uma branch de árvore (qualquer branch todo/), liste as branches da árvore (git branch --list 'todo/<ROOT-ID>-*' 'todo/<ROOT-ID>.*') e leia o nó de cada uma em git show <branch>:TODO.md. Um nó que é [x] em uma branch ainda não mesclada na branch de seu pai (git merge-base --is-ancestor <branch> <parent branch> falha) parou antes de sua mesclagem: termine essa mesclagem e não faça mais nada (/todo-continue etapa 2). Um nó que é [/] é retomado, mais profundo primeiro. Um nó que é [!] em qualquer uma das branches da árvore conta como [!] em todos os lugares (não trabalhável; seus ancestrais esperam), mesmo onde outra branch ainda o mostra como [ ]; uma branch cujo nó não está mais no TODO.md de sua branch pai (descartado) é ignorada; uma branch já mesclada na branch de seu pai é excluída com git branch -d. Pule isso na branch base.
Pistas
Uma pista é um trilho nomeado de árvores raiz que um contexto de agente trabalha sozinho, em ordem. Lane: <nome> (uma letra minúscula, depois letras minúsculas, dígitos ou travessões) em uma raiz coloca toda a sua árvore nessa pista; filhos herdam, e uma raiz sem ela está na pista main (portanto --lane main seleciona essas raízes). Pistas são contexto, não tarefas: uma pista pode conter uma tarefa ou muitas, pistas executam em paralelo entre si (/todo-continue pode receber --lane <nome> ou --all-lanes). O estado de uma pista está em seu Lane: no TODO.md da base. Uma pista bloqueada ou vazia é ignorada pelo processamento em lote. Ao executar em lote, o trabalho de cada pista é passado para um subagente.
Definição de Pronto
Cada nó, quando mesclado, deve:
- ✅ Fazer o que seu
Done when:diz. - ✅ Não quebrar nenhum teste existente (incluindo o comando de regressão se houver).
- ✅ Passar seu próprio comando de verificação (aquele em
Done when:). - ✅ Adicionar à documentação se aplicável.
- ✅ (No modo git) Estar em seu próprio commit ou conjunto de commits com uma mensagem de commit que siga Conventional Commits e inclua o ID do nó.
- ✅ (Pai) Mesclar todos os filhos e eles devem estar
[x].
Antes que um drain raiz ocorra, a árvore inteira deve:
- ✅ Cada folha estar
[x]e mesclada. - ✅ Nenhum nó
[!]em nenhum lugar. - ✅ O comando de regressão do projeto passar (ou
npm testse não houver nenhum). - ✅ O
CHANGELOG.mdser atualizado (pelo drain).
Invariantes
Estas são verificadas no início de cada comando /todo-* (e em /todo sozinho se TODO.md existir):
| # | Invariante | O quê verificar |
|---|---|---|
| 1 | Um estado ativo | No máximo um [/] em TODO.md. |
| 2 | IDs não duplicados | Nenhum ID aparece duas vezes em TODO.md. |
| 3 | Hierarquia de IDs | FEAT-002.1 só pode existir se FEAT-002 existir. |
| 4 | Nenhum órfão | Nenhum nó filho sem pai. |
| 5 | Campos obrigatórios | Cada nó tem Done when: com um comando entre crases. |
| 6 | Marcadores de estado válidos | Apenas [ ], [/], [!], [x]. |
| 7 | Nível máximo | Nenhum nó mais profundo que 3 níveis. |
| 8 | Contexto claro | Nenhum nó ativo e bloqueado simultaneamente (State e Blocked). |
| 9 | Commits da árvore limpa | (Modo git) Nenhuma alteração não preparada em TODO.md, CHANGELOG.md, docs/plans/*.md ou README.md (backlog) na base, a menos que seja uma edição de nó ativo. |
| 10 | Nenhuma alteração de rede | Nenhum comando git que toque na rede (fetch/pull/push) é emitido. |
Falhar em qualquer invariante interrompe o comando e relata a falha.
Fluxo de drain
Um drain move uma raiz concluída ([x]) e suas subárvores para CHANGELOG.md. Isso é acionado por /todo-continue quando uma raiz é [x] e sua árvore é toda [x]. O drain:
- Coleta a entrada do changelog: o prefixo da raiz determina o cabeçalho (Added/Fixed/Changed).
- Adiciona uma entrada formatada sob
## [Unreleased]. - Altera a raiz de
[x]para o estado normal (removido da árvore? Na verdade, marcado como[x]ainda, mas não mais rastreado? O drain não altera TODO.md; em vez disso, o drain é uma etapa antes da liberação. A liberação torna[Unreleased]uma versão.)
Nota: O drain é detalhado em todo-continue. O esboço acima está correto.
Guardrails
- Nunca modifique
TODO.mdem qualquer lugar que não seja um nó de tarefa ou seus campos. - Nunca execute comandos git que toquem na rede.
- Nunca assuma que um nó está concluído sem executar seu
Done when:. - Nunca ignore um
[!]nó em uma branch da árvore. - Sempre verifique a covariância de tamanho ao adicionar/remover nós.
- Sempre preserve a nova linha final do arquivo.
- Sempre use caminhos explícitos ao preparar arquivos de backlog para commit.
Comandos não envolventes
/todo-init,/todo-plan,/todo-add,/todo-continue,/todo-update,/todo-status,/todo-report,/todo-release.- Cada um é independente e não chama outro.
Perguntas frequentes
- O que acontece se eu executar
/todosem um TODO.md? Ele apenas imprime a lista de comandos e informa que nenhum TODO.md foi encontrado. - Posso usar isso sem git? Sim. Avisa uma vez por comando e rastreia tudo em
State:. - Quantas tarefas posso ter? Quantas couberem. Mas folhas devem caber em uma janela de contexto (5 arquivos).
- Como escolho uma complexidade? Baixo = mecânico, médio = investigação, alto = raciocínio difícil.
- Os IDs mudam se eu reordenar tarefas? Não. IDs são fixos.
Referências
reference/git-flow.md: Detalhes do fluxo de branches e worktrees.reference/rtm.md: Matriz de rastreabilidade de requisitos (opcional).docs/status.html: Página de status HTML gerada por/todo-report.