CORTEX — Contrato da Fonte de Documentação
Versão: 1.1.0 · Data: 2026-10-14 · Status: Rascunho · Owner: Plataforma Caminho canônico:
cortex-docs/meta/DOC_SOURCE_CONTRACT.md
Este documento define como os documentos do cortex-docs são estruturados na fonte para serem consumidos por vários canais a partir de uma verdade só: leitura humana online (HTTP), consulta por IA (MCP, "conteúdo certo no ponto certo") e, depois, treino de devs (RAG sobre o próprio corpus). A fonte é o markdown; os consumidores leem metadados estáveis que este contrato fixa. Rascunho pendente de revisão.
A documentação é tratada como dado endereçável registro a registro — mesmo princípio do RAG (cortex-docs/architecture/RAG_AND_INGESTION.md): cada regra é uma unidade com identidade estável, recuperável isoladamente.
1. Front-matter por documento (Obrigatório)
Todo documento abre com front-matter YAML (entre ---), máquina-legível, antes do título humano. O cabeçalho em blockquote (>) é mantido para leitura humana e, a prazo, pode ser gerado do front-matter.
| Campo | Tipo | Função |
|---|---|---|
id |
slug | Identidade do documento (= slug_namespace). Estável, kebab-case, inglês. |
title |
string | Título humano. |
version |
semver | Igual ao cabeçalho. Coerente com a governança do doc (UNISCALE §31.1). |
date |
YYYY-MM-DD |
Data da versão. |
status |
enum | rascunho | em-evolucao | estavel. Vocabulário fechado. |
owner |
slug | Responsável (plataforma). |
canonical_path |
path | Caminho canônico — fonte única (UNISCALE §31.5). |
slug_namespace |
slug | Prefixo dos slugs de regra deste doc (geralmente = id). |
siblings |
lista de paths | Documentos irmãos. |
O front-matter tem de ser YAML válido. Em particular, valor que contenha : (dois-pontos seguido de espaço) vai entre aspas — title: "CORTEX — crm-connector (janela de gestão: cards no CRM)". Sem as aspas, o YAML lê o : como separador de mapa e o bloco inteiro fica ilegível; o serviço de documentação pula o doc e serve o índice sem ele, calado (foi o que houve com o CRM_CONNECTOR.md v0.2.0). O linter da fonte parseia o bloco com yaml.safe_load e reprova, com arquivo, linha e coluna — título com dois-pontos é natural em português, então o gate tem de pegar.
2. Slug de regra (Obrigatório)
Cada regra/seção endereçável recebe um slug nominal estável:
<namespace>.<area>.<conceito>
- kebab-case, inglês (UNISCALE §2, §4). O slug é identificador técnico, não prosa.
namespace— vem do front-matter do doc. Namespaces estáveis:uniscale,ecosystem,rag,doc.area— agrupamento fechado por namespace (tabela abaixo). Área nova só com atualização deste contrato.conceito— a regra específica (point-id,casing,event-envelope).
Áreas fixas por namespace:
| Namespace | Áreas |
|---|---|
uniscale |
naming, types, columns, constraints, lineage, qdrant, mongo, events, service-internals, git, governance, data-architecture |
rag |
principles, data-model, qdrant, outbox, boleto |
ecosystem |
ownership, services, communication, connectors, external-platforms |
doc |
frontmatter, slug, rule, consumers |
ragé narrativo/design e hoje não carrega@rule. Oecosystempassou a carregar@ruleem docs dedicados de serviço/connector — áreaservices(STORAGE_SERVICE.md,PAYMENT_SERVICE.md) e áreaconnectors(CONNECTORS.md) — enquanto o doc narrativoECOSYSTEM.mdem si segue sem marcadores. As demais áreas ficam reservadas para quando uma regra de nível for promovida ali.
Exemplos: uniscale.qdrant.point-id, uniscale.naming.casing, rag.outbox.sync, doc.slug.grammar.
3. Marcador de regra (Obrigatório)
Logo abaixo do título da seção, um comentário HTML (invisível no render, parseável no build):
### 26.3. Identidade do point (Obrigatório)
<!-- @rule id=uniscale.qdrant.point-id level=obrigatorio since=2.0.0 -->
Campos do marcador:
| Campo | Obrigatório? | Valor |
|---|---|---|
id |
sim | O slug (seção 2). |
level |
sim | obrigatorio | recomendado | permitido (espelha o rótulo humano). |
since |
sim | Versão do doc em que a regra surgiu. |
status |
não | active (default) | deprecated | superseded-by=<slug>. |
Escopo (Obrigatório): recebem @rule apenas as seções cujo título declara nível Obrigatório ou Recomendado — ou cujo marcador traz status=deprecated / superseded-by=<slug>, caso em que o título dispensa rótulo de nível (a §4 exige que o slug aposentado siga marcado, e o título de uma regra substituída anuncia (Substituída), não o nível que ela tinha). Seções informativas, intros de seção e nível Permitido não recebem marcador — não são regras endereçáveis.
O sentinela @rule torna os marcadores greppáveis e delimita o início lógico de cada regra (o "chunk" da regra vai do marcador até o próximo título de mesmo nível).
4. Estabilidade do slug (Obrigatório)
- Slug publicado é imutável. Pode-se renumerar a seção (§26.3 → §27.1) ou reescrever o título e o texto — o slug não muda. O número é humano; o slug é a chave de máquina.
- Slug nunca é reusado. Regra removida/fundida/dividida marca o slug antigo
status=deprecated(ousuperseded-by=<novo-slug>), nunca o aponta para outra coisa. - Referência cruzada migra para slug ao longo do tempo. Hoje os docs citam "seção 31.3"; o canal de máquina (MCP) chaveia por slug. Citações humanas por número continuam válidas até a migração.
5. Como os consumidores usam (Permitido — informativo)
- HTTP (humano): o build renderiza cada regra com âncora = slug → link profundo estável (
/uniscale#uniscale.qdrant.point-id). - MCP (IA):
get_rule("uniscale.qdrant.point-id")devolve texto +level+version;list_rules(namespace, level)filtra (ex.: sóobrigatorio);search_docs(query)retorna slugs. - Treino (RAG): cada bloco
@ruleé um chunk natural — ingestão por regra, com o slug como identidade preservada (RAG_AND_INGESTION §3.2/§4.1). Documentação reaproveita o pipeline do produto.
6. Marcador de seção @section (âncora estável em doc narrativo) (Obrigatório)
A âncora de uma seção é derivada do texto do título: renomear ou renumerar o título muda a âncora, e nada avisa (título repetido ainda recebe sufixo posicional, então inserir uma seção no meio redistribui os sufixos das seguintes). Em doc narrativo (ecosystem, rag) não há @rule — a âncora de seção é a única forma de endereçar aquele conteúdo. Com get_section(doc_id, anchor) na face MCP, a âncora deixou de ser só fragmento de URL e virou chave de máquina, igual ao slug — e uma reescrita de título a invalida em silêncio (o mesmo sintoma que a §4 existe para impedir).
O marcador resolve, no espírito do @rule:
## 3. Glossário de fronteira: de quem é cada coisa
<!-- @section id=ecosystem.map.glossary -->
- Opcional, só nas seções citáveis. Onde não houver
@section, a âncora derivada do título segue valendo — nada quebra por omissão. - Gramática do
id:<namespace>.<area>.<conceito>, kebab-case, inglês, comnamespace==slug_namespacedo doc. Diferente do slug de regra (§2), aareaé LIVRE — não presa à tabela fechada da §2, que foi desenhada para regra, não para seção narrativa (daíecosystem.map.glossary, commapque não é área de regra). - Estável como o slug (§4):
idimutável e nunca reusado; renumerar ou reescrever o título não muda oid. A unicidade é global, no mesmo espaço dos slugs de@rule— um@sectionnunca colide com um@rule. - Não é regra:
@sectionnão carregalevel/since, não exige título de nível, não entra na contagem de@rulenem na exigência da §3 de "todo título Obrigatório/Recomendado tem marcador". - Consumo: o parser usa o
@sectioncomo âncora quando presente e cai no título derivado onde não houver — âncora antiga continua funcionando.
Exemplo aplicado
Antes (humano puro):
### 26.3. Identidade do point (Obrigatório)
- O `id` do point é o `id` (UUIDv7) do chunk no Postgres...
Depois (humano + máquina):
### 26.3. Identidade do point (Obrigatório)
<!-- @rule id=uniscale.qdrant.point-id level=obrigatorio since=2.0.0 -->
- O `id` do point é o `id` (UUIDv7) do chunk no Postgres...
Nada muda na renderização humana; o build passa a saber que aquilo é a regra uniscale.qdrant.point-id, obrigatória, desde a 2.0.0.
CHANGELOG
| Versão | Data | Autor | Resumo |
|---|---|---|---|
| 1.1.0 | 2026-10-14 | Plataforma | Dois pedidos de formato da sessão do docs-service. §6 nova (doc.rule.section-marker): marcador @section id=... dá âncora estável a seção narrativa (ecosystem/rag), no espírito do @rule — necessário porque a face MCP passou a servir get_section(doc_id, anchor) e a âncora derivada do título quebrava deep-link em silêncio ao renomear/renumerar. id em espaço próprio: formato <namespace>.<area>.<conceito> e namespace do doc, mas área LIVRE (não presa à tabela fechada da §2, que é para regra), imutável/nunca reusado (§4) e único no mesmo espaço dos @rule; opcional (só seções citáveis), não é regra (sem level/since/título de nível). §1 (esclarecimento): valor de front-matter com : tem de ir entre aspas — sem isso o YAML fica ilegível e o indexador pula o doc calado (incidente do CRM_CONNECTOR.md v0.2.0); o linter passa a parsear o bloco com yaml.safe_load e reprovar com arquivo/linha/coluna. MINOR. |
| 1.0.3 | 2026-09-10 | Plataforma | Resolve tensão entre a §3 e a §4: a §4 (doc.slug.stability) manda a regra aposentada seguir marcada (deprecated/superseded-by=), mas o escopo da §3 só admitia marcador sob título que declara Obrigatório/Recomendado — e o título de uma regra substituída anuncia (Substituída). Obedecer a uma violava a outra (ecosystem.services.tracking-merge-alias, TRACKING_SERVICE §15-bis). A §3 passa a admitir marcador sem rótulo de nível no título quando o status é de regra aposentada. Nenhuma regra ativa muda; o linter da fonte acompanha. PATCH. |
| 1.0.2 | 2026-06-15 | Plataforma | Atualiza a nota da §2 (grammar): o namespace ecosystem deixou de ser "sem @rule" — passou a carregar regras via docs dedicados, na área services (storage-service, payment-service) e na área connectors, enquanto o ECOSYSTEM.md narrativo segue sem marcadores. Correção de fato na prosa informativa; nenhuma regra @rule alterada. PATCH. |
| 1.0.1 | 2026-06-02 | Plataforma | Corrige inconsistência da própria fonte: remove o marcador @rule da §5 (doc.consumers.usage), que era nível Permitido e portanto não deveria ter marcador pela regra de escopo da §3. PATCH. |
| 1.0.0 | 2026-06-02 | Plataforma | Contrato inicial da fonte de documentação: front-matter YAML por documento, slug nominal estável por regra (<namespace>.<area>.<conceito>), marcador @rule (comentário HTML com id/level/since/status), regras de estabilidade do slug (imutável, nunca reusado, renumeração não afeta) e mapa de consumo (HTTP humano, MCP para IA, RAG de treino por regra). Rascunho pendente de revisão. |