O modelo
05 · Anatomia do repositório
Como o repositório de uma stack é em três momentos: recém-nascido (Fase 0), com a stack definida e a fundação pronta (fim da Fase 2), e maduro (Fase 3 em diante, com a nenhuma stack em particular).
O esqueleto que nunca muda
Seja qual for a tecnologia, estas pastas existem em toda stack, com o mesmo papel:
| Pasta | Papel | Dono do conteúdo |
|---|---|---|
AGENTS.md | Papel: Regras para qualquer agente de IA (fonte única) | Dono do conteúdo: modelo + stack |
CLAUDE.md | Papel: Importa o AGENTS.md (@AGENTS.md), que o Claude Code carrega em toda sessão (+ particularidades do Claude Code, se houver) | Dono do conteúdo: modelo |
ARQUITETURA | Papel: Versão da arquitetura de que a stack nasceu / para a qual atualizou | Dono do conteúdo: mantenedor |
docs/ARCHITECTURE.md | Papel: Visão técnica de alto nível, com diagramas | Dono do conteúdo: stack |
docs/stack.md | Papel: Ficha da stack: tecnologia, versões, fonte de cada versão | Dono do conteúdo: stack (Fase 1) |
docs/produto/ | Papel: Visão de produto: para quem, o quê, o método do negócio | Dono do conteúdo: stack |
docs/decisoes/ | Papel: ADRs da stack (pré-escritas + próprias), o índice, os pedidos à arquitetura e, em organizacao/, a cópia das ORGs | Dono do conteúdo: modelo + stack; organizacao/ só pela versão da arquitetura |
docs/solucoes/ | Papel: Detalhes de implementação que não cabem na arquitetura | Dono do conteúdo: stack |
docs/guias/ | Papel: Passo a passo operacional | Dono do conteúdo: modelo (guias padrão) + stack |
docs/acesso/ | Papel: Permissões e perfis de cada aplicação | Dono do conteúdo: stack |
docs/design-system/ | Papel: Aplicações e famílias, mapa de estados, pedidos, aprendizados | Dono do conteúdo: stack |
docs/screenshots/ | Papel: Acervo de capturas (Git LFS) — opcional | Dono do conteúdo: gerado |
openspec/ | Papel: config.yaml, specs/ (verdade viva), changes/ (em curso e arquivo) | Dono do conteúdo: stack |
e2e/ | Papel: Harness, agrupamentos, cenários, casos, setups | Dono do conteúdo: stack |
deploy/<app>/ | Papel: Tudo que o Kamal precisa para uma aplicação | Dono do conteúdo: stack |
eng/ | Papel: Scripts versionados: banco local, Keycloak, E2E, capturas, backup, verificações | Dono do conteúdo: modelo + stack |
vendor/hibex/ | Papel: Cópia do design system, nunca editada à mão | Dono do conteúdo: script do mantenedor |
compose.yaml | Papel: Ambiente local descartável: banco, Keycloak, apps, observabilidade (perfil) | Dono do conteúdo: stack |
Momento 1 — recém-nascida (Fase 0)
Tudo o que depende de tecnologia está ausente ou em lacuna. A árvore é a mesma para qualquer stack.
<plataforma>-stack-<produto>/
├── README.md # "Estado: Fase 1 — definindo a stack"
├── AGENTS.md # regras completas; seção "Stack" em lacunas
├── CLAUDE.md # → AGENTS.md
├── ARQUITETURA # arquitetura-vX.Y.Z (escrito pelo new-stack.sh)
├── .editorconfig · .gitattributes · .gitignore
├── .claude/
│ ├── settings.json # hooks
│ ├── commands/opsx/ · skills/ # /opsx:* e skills openspec-*, do openspec init (new-stack.sh)
│ └── hooks/
│ ├── block-git-writes.py # Git e GitHub de escrita negados ao agente
│ ├── block-infra.py # Kamal, ssh, segredos e admin de host real negados
│ ├── shell_commands.py # a leitura de comandos de shell dos dois
│ └── test_*.py # os testes de cada hook
├── .github/workflows/ci.yml # só: lacunas, versões fixas, segredos, ordem do TDD, testes dos scripts, openspec validate
├── docs/
│ ├── ARCHITECTURE.md # esqueleto com lacunas
│ ├── stack.md # ficha da stack — toda em {{LACUNA:…}}
│ ├── produto/visao.md # {{LACUNA:…}}
│ ├── produto/glossario.md # terminologia do domínio, vazia
│ ├── decisoes/
│ │ ├── README.md # índice
│ │ ├── template.md
│ │ ├── ADR-0001…0011-*.md # ADRs pré-escritas, com lacunas
│ │ ├── pedidos-a-arquitetura.md # vazio, com o formato
│ │ └── organizacao/ # ORG-0001…0025: cópia, nunca editada
│ ├── solucoes/README.md
│ ├── guias/
│ │ ├── README.md
│ │ ├── fluxo-openspec.md # pronto (independe da stack)
│ │ ├── nova-aplicacao.md # pronto: acrescentar uma aplicação
│ │ └── definir-a-stack.md # o roteiro da Fase 1 e o catálogo das lacunas
│ ├── acesso/README.md # modelo do documento de acesso por aplicação
│ └── design-system/
│ ├── aplicacoes.md # {{LACUNA:…}}
│ ├── estados.md # vazio, com o formato
│ ├── pedidos.md # vazio, com o formato
│ └── aprendizados.md # vazio, com o formato
├── e2e/
│ ├── README.md # o que vem no modelo e o que a change e2e-base acrescenta
│ └── hierarchy/ # o harness do E2E, pronto (igual em toda stack; não se edita)
├── deploy/
│ └── README.md # os esqueletos do deploy.yml e do .kamal/secrets, com o contrato da plataforma
├── openspec/
│ ├── config.yaml # contexto e regras; trechos em lacuna
│ ├── specs/ # vazio
│ └── changes/archive/ # vazio
└── eng/
├── README.md
├── gaps.sh # falha se houver lacuna
├── pinned-versions.sh # falha se houver versão flutuante
├── deploy-secrets.sh # falha se um .kamal/secrets tiver valor ou não bater com o deploy.yml
├── tdd-order.sh # falha se uma tarefa de código vier antes do teste
├── tools.versions # versões das ferramentas da CI e dos scripts
├── tests/ # os testes dos scripts e do openspec/config.yaml
└── sketches/ # o kit de rabiscos (fontes do npm: desenha desde a Fase 0)Momento 2 — stack definida e fundação pronta (fim da Fase 2)
Aparece o código e tudo o que a fundação entrega. Os nomes entre <> são da stack.
Os blocos marcados (tecnologia) variam de forma conforme a ficha.
<plataforma>-stack-<produto>/
├── README.md # pré-requisitos com versão; como rodar; status
├── AGENTS.md # seção "Stack" preenchida
├── CLAUDE.md · ARQUITETURA
├── compose.yaml # db · keycloak · <apps> · perfil observability
├── <arquivos de build> # (tecnologia) ex.: settings.gradle.kts + gradle/libs.versions.toml
├── <produto>-<modulo-comum>/ # (tecnologia) domínio, regras, migrations
├── <produto>-<app-a>/ # (tecnologia) aplicação A
├── <produto>-<app-b>/ # (tecnologia) aplicação B
├── e2e/
│ ├── package.json · package-lock.json · .nvmrc · tsconfig.json · playwright.config.ts
│ ├── hierarchy/ # o harness, do modelo (agrupamento/cenário/caso, setups, capturas)
│ ├── steps/ # actors.ts (os perfis) e as ações reutilizáveis, pela interface
│ └── groups/
│ └── identidade/
│ ├── group.ts # setup do agrupamento
│ ├── login/ # cenário
│ │ ├── scenario.ts # setup do cenário
│ │ ├── entra-com-cada-perfil.case.ts
│ │ └── recusa-sem-permissao.case.ts
│ └── logout/…
├── deploy/
│ ├── README.md # os esqueletos, do modelo
│ ├── <app-a>/ Dockerfile · config/deploy.yml · .kamal/secrets
│ └── <app-b>/ …
├── eng/
│ ├── dev-db.sh · e2e.sh · gaps.sh · pinned-versions.sh
│ ├── auth/ README.md · provision.sh · dev-realms.sh · dev-realms/*.json
│ ├── backup/restore-db.sh # um restore-<armazenamento>.sh por armazenamento com dados
│ │ # (e o backup-<armazenamento>.sh, se a imagem não traz o backup)
│ └── observability/ tempo.yaml · grafana-datasources.yaml
├── vendor/hibex/ # cópia do design system (VERSAO)
├── docs/
│ ├── ARCHITECTURE.md · stack.md
│ ├── decisoes/ADR-0001…0011, 0012… # pré-escritas aceitas + as primeiras próprias; organizacao/
│ ├── acesso/<app-a>.md · <app-b>.md
│ ├── design-system/aplicacoes.md · estados.md · pedidos.md
│ └── guias/ desenvolvimento-local · testes · implantacao · identidade ·
│ backup-e-restauracao · observabilidade-local ·
│ atualizar-design-system · fluxo-openspec
└── openspec/specs/ acesso-<app-a> · acesso-<app-b> · observabilidade · aparenciaO vendor/hibex/ fica sempre na raiz. Uma linguagem que reserva a pasta vendor/ (o Go a trata
como vendoring de módulos, ao lado do go.mod) põe o código numa subpasta, como src/, e o
build copia do vendor/hibex/ só o que a aplicação embute.
Momento 3 — madura
Uma stack madura tem dezenas de ADRs próprias, uma spec e um agrupamento E2E por capability, e o produto. O esqueleto é o mesmo dos outros momentos: as pastas não mudam, só enchem.
Como cada pasta cresce
A relação que se mantém em toda fase: cada capability em openspec/specs/ tem um
agrupamento em e2e/groups/ com o mesmo nome, e cada requisito da spec tem um
cenário. Isso torna visível o que está especificado e não está testado de ponta a ponta.