Começar
Aparência

Vale na hora e fica lembrada neste navegador.

Decisões

ADR-0006 — Criar e atualizar uma stack a partir da tag, rodando daqui contra a stack

Contexto

Uma stack nasce do eng/new-stack.sh, que tira os arquivos da tag escolhida (git archive), mas roda com a lógica da árvore em que está: um new-stack.sh de uma versão futura monta a v0.1.0 com o seu próprio jeito de montar.

Atualizar não tem ferramenta. A change arquitetura-X-Y-Z da stack lê o "Para as stacks" e copia cada arquivo à mão. Na primeira adoção, a da piloto, foram 17 tarefas, e 47 arquivos entraram como cópia exata da tag, conferidos um a um com cmp: as ORGs, o e2e/hierarchy/, os scripts de eng/ e os testes deles, o deploy/README.md e dois guias. Esse trabalho se repete em cada stack e a cada versão, e cada uma pode errar de um jeito. A piloto, por exemplo, copiou a pasta das ORGs inteira e levou junto o template.md, que é deste repositório e que o new-stack.sh nunca copia.

O modelo mistura dois tipos de arquivo, e só um deles pode ser substituído:

  • partes da arquitetura: iguais em toda stack, nunca editadas nela. A piloto não tinha mexido em nenhuma, com uma exceção: o hook de Git, ao qual acrescentou uma regra (o pedido "O hook do modelo não barra o atualizador do design system");
  • moldes: viram da stack no nascimento (AGENTS.md, README.md, as ADRs pré-escritas, a ficha, a CI, os guias com lacunas). Só uma change os atualiza.

O design system já passou por isso (ADR-0079 de lá): quem sabe instalar a versão X é a versão X, rodada do próprio repositório contra o produto, que não guarda script de atualização.

Decisão

  1. Duas operações, rodadas daqui, de um checkout na tag da versão, sem mudanças locais:

    • criar: eng/new-stack.sh <destino> --platform … --product …, que passa a ler a versão do próprio checkout (o --version sai; o --draft continua, para provar o modelo antes de uma tag);
    • atualizar: eng/atualizar-stack.sh --alvo=<raiz da stack>.

    São duas porque criar preenche lacunas e roda o openspec init, e atualizar não toca em molde. Nenhuma das duas faz commit.

  2. As partes da arquitetura são substituídas por inteiro na atualização. O que sai de uma versão sai da stack. A lista é escrita, numa tabela "da arquitetura / da stack" no capítulo 05, e começa com o que a piloto copiou sem adaptar:

    • docs/decisoes/organizacao/ORG-*.md;
    • e2e/hierarchy/;
    • eng/gaps.sh, eng/pinned-versions.sh, eng/tdd-order.sh, eng/deploy-secrets.sh e os testes deles;
    • os hooks de .claude/hooks/ e os testes deles;
    • o motor do kit de rabiscos (eng/sketches/, sem os quadros);
    • os guias e esqueletos sem lacuna (deploy/README.md, docs/guias/definir-a-stack.md, docs/guias/nova-aplicacao.md).
  3. Um manifesto na stack: o ARQUITETURA continua com a versão na primeira linha, e um ARQUITETURA.manifest lista cada parte com o hash. Um hook barra a edição dessas partes pelo agente, como o block-vendor-hibex.py barra a da cópia do design system, e o atualizar-stack.sh recusa uma stack com parte alterada.

  4. Os hooks têm um ponto de extensão da stack: uma regra que só a stack quer vai num arquivo dela, lido pelos hooks da arquitetura; uma regra que vale para toda stack é pedido para cá.

  5. O resumo diz o que conferir: a versão anterior, as partes que entraram, mudaram e saíram, e o "Para as stacks" de cada versão no meio.

  6. O "Para as stacks" se divide em duas partes: "chega pela cópia", que só se confere, e "faça na change", com os moldes. A change arquitetura-X-Y-Z fica só com a segunda.

  7. As partes copiadas ficam fora da ordem do TDD na change de adoção. Elas chegam testadas pela CI deste repositório, e o eng/tdd-order.sh não pede, para elas, o teste antes do código.

  8. Proteções: este repositório na tag e sem mudanças; a stack num repositório Git, com as partes da arquitetura sem mudanças por commitar.

  9. Quem roda é sempre uma pessoa, o mantenedor. Nem o agente daqui nem o da stack rodam as duas ferramentas contra uma stack; o da stack pede a versão nova.

  10. Mudar este contrato (a lista das partes, o manifesto, os argumentos) pede, na 0.x, uma versão menor com o seu "Para as stacks"; a partir da 1.0, uma versão maior.

Alternativas consideradas

AlternativaPor que não
Continuar com a adoção à mãoPor que não: cada stack refaz as mesmas cópias a cada versão; a piloto levou 17 tarefas, e a maior parte era copiar e conferir
Uma ferramenta só, com dois modos (como o atualizar.mjs do design system)Por que não: criar preenche lacunas e inicializa o OpenSpec, e atualizar não toca em molde: os dois modos teriam pouco em comum
O atualizador dentro da stack, baixando a tagPor que não: põe na stack um script, rede e acesso a este repositório, para um passo que só o mantenedor dá; o design system tentou e voltou atrás (ADR-0079 de lá)
Substituir também os moldes, com mergePor que não: um molde já preenchido é texto da stack; um merge automático de prosa erra sem avisar

Consequências

  • Uma stack se atualiza com um comando e uma change pequena, só com os moldes.
  • A tabela "da arquitetura / da stack" passa a ser contrato: mudar um arquivo de lado é mudança de versão.
  • A stack ganha um manifesto e um hook a mais, e perde o direito de editar as partes da arquitetura: o ajuste vira pedido.
  • A primeira versão com o atualizador é a arquitetura-v0.2.0. Uma stack na v0.1.0 faz a primeira atualização com ele, e o manifesto nasce nela.