# Usando o Anchors > Documentação de USO. O `README.md` e os 11 documentos de pilar (`SPEC.md`, > `QUALITY.md`, `TRACEABILITY.md`…) explicam o CONCEITO — por que o framework existe e > como ele pensa. Este arquivo explica o que você faz na prática: que arquivos o projeto > precisa ter, o que cada um contém, e o que cada gate cobra. > > Ele nasceu de uma falha concreta: uma sessão de trabalho travou por não saber o formato > de uma spec. A informação existia — em `anchors new spec --list-sections` e na mensagem > de erro de um gate — mas nada apontava para lá, e o guide embutido chegava a instruir a > descobrir errando ("rode `anchors check`; se reprovar, a mensagem diz o formato"). > Documentação atrás de subcomando só é achada por quem já sabe que ela existe. ## 1. Os arquivos que o projeto precisa ter | arquivo | quem escreve | serve para | | --- | --- | --- | | `PROJECT.md` | o agente, entrevistando você (`anchors guide project`) | o resumo TÉCNICO do projeto: stack, paradigma, estrutura macro, extensões, indentação, ferramental. Lido antes de escrever cada arquivo | | `INSIGHTS.md` | o mesmo, na mesma passada | a transcrição da entrevista: cada pergunta, cada resposta, e o que foi DESCARTADO e por quê | | `anchors.yaml` | `anchors init` (e você refina) | declara as CAMADAS (que arquivo é o quê), os GATES ligados, e o dialeto do projeto | | `anchors.graph.yaml` | `anchors map build` | o mapa: quem depende de quem. Gerado, versionado, nunca editado à mão | | `guides/*.md` | você | a régua de cada artefato. O `init` semeia `HEADER_GUIDE.md` e `SPEC_GUIDE.md` | | `.spec.md` | você (via `anchors new spec`) | o que a unidade faz, com cada regra catalogada e identificada | | `.feature` | você (via `anchors new feature`) | os cenários de comportamento, cada um citando o código da regra | | `.test.*` | você | a prova executável, citando o código no nome do caso | | `.anchors/` | o CLI | fila de trabalho, espelho da última verificação, issues. Não versionado | A UNIDADE é `spec` + `feature` + `test` amarradas pelo mesmo código de identidade. É o que permite perguntar "esta regra tem cenário? tem teste? o teste passou?" sem ler o código. ## 2. Começando num projeto **Projeto que ainda NÃO existe** (diretório vazio): antes de tudo, há a fase DESCOBRIR. O `anchors init` INFERE a Estrutura do que está no disco — num diretório vazio não há o que inferir. Então o agente que opera o Anchors lê `anchors guide project` e entrevista você em cinco etapas (propósito e forma → linguagem → arquitetura e paradigma → estrutura macro e convenções → ferramental e formatação), uma pergunta por vez. No fim ele escreve `PROJECT.md` (as decisões) e `INSIGHTS.md` (a transcrição, com o que foi descartado). Só então o `init` tem o que perguntar — e você responde com o que está no PROJECT.md. ```sh anchors init # perguntas → anchors.yaml + guides semeados (precisa de terminal) anchors map build # constrói o mapa; TODO arquivo novo só existe para os gates depois disto anchors check --all # roda os gates sobre tudo anchors doctor # saúde sistêmica: órfãos, camadas frouxas, arestas mortas ``` Num projeto que JÁ EXISTE, não tente conformar tudo de uma vez. Ligue os gates de ESTRUTURA primeiro (eles medem o código como está, sem exigir spec), deixe os de unidade informativos, e promova conforme as specs nascem. Ligar tudo de uma vez produz centenas de issues no primeiro dia e ninguém lê a lista. ## 3. Escrevendo uma spec Não escreva do zero — o CLI emite o esqueleto já conforme: ```sh anchors new spec --out /.spec.md anchors new spec --list-sections # as 25 seções, com QUANDO usar cada uma ``` Uma regra é **catalogada** quando tem código E lugar estruturado. Menção solta em prosa não conta: ```md ### LOGIX-B01 — descrição da regra <- cabeçalho (preferido) | `LOGIX-B02` | descrição | <- linha de tabela - **LOGIX-B03** descrição <- bullet-negrito ``` A LETRA diz a natureza da regra (`S` estado, `A` ação, `V` validação, `R` permissão, `X` restrição…). O projeto declara as suas em `rule_types`; sem declaração valem as canônicas. O COMPRIMENTO do código é do projeto (`code_lengths`) — 4, 5, ou os dois durante uma migração. ## 4. Os gates Um gate CONFRONTA dois artefatos e devolve um veredito. **Bloqueante** barra a promoção; **informativo** registra e não barra (é a maturação: liga-se informativo, promove-se depois). Quatro vereditos, e a diferença importa: - **✓ passou** — confrontou e está conforme. - **✗ reprovou** — vira issue. Bloqueante: barra. - **⚠ divergiu** — olhou, algo não bate, mas não barra. - **~ indeterminado** — o gate rodou e NÃO TEVE O QUE MEDIR. Não é aprovação: é cobertura que não existe. Um projeto sem specs tem quase tudo aqui. ### Referência | `cenario-identidade` | dois cenários da MESMA feature não podem ter o mesmo código | | `cenario-letra-declarada` | a letra do código de cenário existe no vocabulário | | `cenario-tipo-alinhado` | a tag de natureza do cenário concorda com a letra do código | | `code-reference-valid` | um código citado por uma spec precisa EXISTIR | | `codigo-catalogado` | o que o código EXPORTA precisa estar na spec — ou dispensado nele | | `contract-status-declared` | a tabela "Contrato de Saída" de uma spec de INTERFACE | | `count-honored` | um NÚMERO que a spec afirma sobre o código precisa bater com o código | | `coverage-delta` | a cobertura de linha deste nó de código CAIU desde a ingestão | | `domain-declared` | a seção `## Domínio` declara o que a unidade ACEITA — e quem garante | | `evidence-fresh` | o placar deste teste vale contra o código de HOJE | | `guide-has-checklist` | um GUIDE de governança deve destilar suas regras em PONTOS DE | | `has-code` | o arquivo carrega um código de cenário (a identidade). Sem código, a | | `header-conforme` | o arquivo tem o BLOCO DE CABEÇALHO do Anchors (`@anchors`) com o | | `layer-boundary` | uma camada não alcança o que não é dela | | `line-coverage` | a cobertura de linha do nó de código está >= 70%? (limiar fixo por | | `mock-carimbado` | o dublê carrega a marca do trecho que ele substitui, e o gate | | `mock-tipado` | todo dublê de teste precisa DERIVAR do módulo que substitui | | `mutation-score` | dos mutantes que rodaram neste arquivo, o teste matou o suficiente? | | `non-empty` | o arquivo não é vazio nem só espaço. Trivial, mas pega placeholders | | `obligation-honored` | confronta as OBRIGAÇÕES TRANSVERSAIS declaradas (`obligations:` | | `open-questions-resolved` | uma spec com pergunta em aberto NÃO está pronta para implementar | | `pagination-honored` | uma função que promete devolver um CONJUNTO ("liste todos", "os | | `placeholder-preenchido` | o esqueleto que o `anchors new` emite tem de ser PREENCHIDO | | `plan-seeds-valid` | um PLANO semeia artefatos (as specs que vão nascer). Este gate | | `prova-cruza-fronteira` | quando uma REGRA afirma relação com outra unidade — "espelha | | `ref-resolves` | o `ref:` de um artefato aponta para a spec que REALMENTE o descreve | | `region-pair-honored` | toda região aberta fecha, e fecha com o próprio código | | `regra-implementada` | a spec cataloga regras; o código tem de mostrar que as realizou | | `route-declared` | uma spec de TELA (layer: screen) declara COMO se chega até ela — a | | `route-exists` | a rota que a spec DECLARA tem de existir no app | | `scenario-asserts` | o passo de RESULTADO de um cenário precisa afirmar um resultado | | `scenario-coverage` | cada código de cenário que a spec DECLARA tem um teste que | | `sibling-guard` | funções IRMÃS (exportadas do mesmo módulo, recebendo o mesmo | | `spec-feature-match` | todo REQUISITO declarado na spec tem ao menos um CENÁRIO na feature | | `spec-sections` | uma spec deve CATALOGAR ao menos uma regra/estado com código — o | | `teste-rastreavel` | um teste ligado a uma feature precisa DIZER o que prova | | `tests-pass` | o nó de teste tem 0 falhas (do resultado de execução ingerido)? | | `trigger-declared` | um gatilho de obrigação CITADO tem de existir | | `no-duplication` | nenhum arquivo de código tem bloco copiado de outro lugar — lê o relatório do jscpd e dá um veredito por arquivo, nomeando o outro lado de cada clone; a calibragem é o `.jscpd.json` (`minLines`, `ignore`, `threshold`) | | `header-valid` | o header `@anchors` da spec e da feature carrega a identidade do artefato | | `unit-complete` | uma spec de camada REGIDA precisa das três peças que a realizam — | | `updated-at-atual` | o `updated_at` do header bate com a data do ÚLTIMO COMMIT que | | `vr-baseline` | o cenário de regressão VISUAL prometido tem imagem de referência | | `test-level-codes` | cada cenário referencia só códigos que o seu nível de teste aceita (`levels` do próprio gate: `allow`/`exclude`) | Gates externos (`run:`) chamam a ferramenta do seu stack (`tsc`, `eslint`, `go vet`) — o Anchors não reimplementa o que a ferramenta já faz, só lê o veredito. O `scope:` decide se o comando roda por arquivo (`node`), com os arquivos como argumento (`batch`) ou uma vez sobre o projeto (`project`). ### Gates GENÉRICOS (você declara quantos quiser) Os da tabela acima são canônicos: perguntam a mesma coisa em todo projeto. Alguns gates, porém, **só existem depois que você diz o que confrontar** — e por isso não têm entrada fixa no catálogo. Você declara um por assunto, cada um com o seu `id`. #### `marker-parity` — a mesma regra nas duas pontas A classe de defeito é o **de-para que se desfaz de um lado só**. Uma regra que vive em dois lugares — a promessa na interface e o cumprimento no servidor — não tem como ser conferida por nenhum gate de arquivo: cada lado, olhado sozinho, está impecável. O que falha é a **relação**, e ela some sem deixar erro. O caso real que o originou: uma página pública lista o que será apagado quando o titular pede exclusão de dados, e o backend apaga. As duas listas nasceram juntas e nada as ligava. Se um escopo passasse a apagar mais (ou menos), a página seguiria exibindo a versão antiga — e o titular consentiria com base nela. ```yaml gates: - name: paridade-exclusao-de-dados id: data-purge-parity # ÚNICO — é por ele que se cita e se dispensa check: marker-parity scope: project blocking: true marker_prefix: data-purge-rule # o prefixo das marcações marker_count: 2 # quantas ocorrências cada regra precisa ter marker_scopes: # e ONDE elas têm de estar (uma por escopo) - apps/landing-page/** - packages/backend/** ``` E no código, dos dois lados: ```ts // @data-purge-rule-conta-completa: o que a página promete apagar ``` ```ts // @data-purge-rule-conta-completa: o que o handler de fato apaga ``` O que vem **depois do prefixo** é o nome da regra, e é ele que emparelha as pontas. O sufixo é livre (letras, dígitos, `-`, `_`) e a marcação pode ser seguida de `:` e da prosa que explica. Três cuidados que o gate já toma por você: - **`marker_scopes` não é enfeite.** Sem ele o gate só conta, e duas marcações do **mesmo lado** somariam 2 — exatamente o caso que ele existe para pegar. Com escopos, a pergunta passa a ser "cada lado tem a sua?", e o laudo **nomeia** o lado que faltou. - **Ausência total não aprova.** Um prefixo que não aparece em lugar nenhum devolve indeterminado, não ✓ — é quase sempre erro de digitação na declaração, e aprovar ali faria o gate parecer vigilante sem vigiar nada. - **Regra órfã também reprova.** Se a regra foi apagada de um lado e esquecida no outro, o gate acusa — some tanto o que falta quanto o que sobra. Declare **um gate por assunto**: `data-purge-parity`, `pricing-parity`, `consent-parity`. Cada um com o seu prefixo e o seu `id`, porque é pelo `id` que o relatório os distingue e que uma dispensa atinge um sem derrubar os outros. ## 5. O ciclo de trabalho ``` (descobrir) → plano → spec → código+feature → teste → confronto ``` O `descobrir` entre parênteses roda UMA vez, só em projeto novo: é o que fixa a linguagem, o paradigma e as convenções antes de o primeiro plano decidir quais specs nascem. Cada passo produz o artefato que o próximo confronta. O `anchors watch` enfileira o próximo passo a cada arquivo salvo; `anchors next` puxa da fila e `anchors done` fecha. Com `workflow.mode: github`, a fila são as issues do repositório (ver `WORKFLOW.md`). ## 6. Quando algo não bate | sintoma | o que é | | --- | --- | | `não é regido pela Estrutura` | o arquivo não casa nenhuma camada do `layers:` — declare a camada ou é arquivo que não deveria estar ali | | gate `~` em tudo | falta o artefato do outro lado da relação (spec sem feature, feature sem teste) | | `X gate(s) declarado(s) sem nada para medir` | o `on:` do gate não casa nenhum nó — crie o artefato ou remova o gate | | `evidência VENCIDA` | o teste passou contra código que já mudou. Rode de novo | | mapa DESATUALIZADO | `anchors map build` — os gates leem o mapa, não o disco | Nunca "conserte" fazendo a âncora mentir sobre o código. Se o código diverge da spec, ou o código está errado (corrija), ou a spec envelheceu (atualize — e isso pode gerar trabalho novo, que é informação, não obstáculo).