A dupla que dá CARA ao motor: @alembic/design guarda o design-system Warm-Neutral como um preset TIPADO (copiado verbatim de docs/design-system.html) e renderers puros — renderHtmlPage emite o shell canônico dos cursos. Em volta, um portão de governança de verdade: pnpm detect roda o impeccable no CI, e um teste do próprio repo prova que o artefato LIGHT sai com zero achados. Ao lado, @alembic/docs transforma uma pasta de Markdown em site estático — com um sanitizador de URL que fecha a porta do XSS.
packages/design/src/themes.ts declara o WARM_NEUTRAL como um ThemePreset de @alembic/contracts — e o comentário de cabeçalho crava a regra de proveniência: "Every token value below is copied VERBATIM from the live :root block of docs/design-system.html … these values are what the impeccable CI detector keys off, so a drift here is a brand-governance bug" (themes.ts:10–19). Paleta, tipografia (serif/sans/mono) e espaçamento viram tokens nomeados; a paleta DARK é um segundo conjunto com os MESMOS nomes (themes.ts:59–74), emitido como override.
Dois tokens contam a história do gate: o accent de texto pequeno em fundo claro é clay-ink: #BE4019 — não o clay: #E75533 (themes.ts:27–28) — e o cinza secundário é g500: #6B6A63 (themes.ts:35): os valores foram calibrados para passar contraste AA sob o detector. E pickTheme nunca lança: id desconhecido cai no default, e o preset escolhido ainda é validado pelo themePresetSchema antes de sair — registry corrompido vira Err, não render quebrado (themes.ts:96–107).
Pense como… o manual de identidade visual de uma marca — mas compilável: em vez de um PDF que o estagiário esquece, um objeto tipado que o CI confere. Onde a analogia quebra: manual de marca não tem safeParse — este tem, e um hex fora do lugar quebra o build, não a estética.
packages/design/src/render.ts é 100% puro: "same preset in, same string out, with no Date.now() / Math.random()" (render.ts:5–7). renderThemeCss achata os tokens num bloco :root { --nome: valor; } (render.ts:50–55); renderDarkThemeCss emite o override :root[data-theme="dark"] a partir da paletteDark (render.ts:66–73); e renderHtmlPage monta o documento completo com o shell canônico do curso: corpo 20.5px, h1/h3 serifadas, h2 mono-uppercase, toggle de dark embutido, camada de animação com guarda de reduced-motion e sidebar opcional com scrollspy (render.ts:133+; o CSS emitido em :229–312). Tudo interpolado passa por escapeHtml (render.ts:23–29).
O detalhe anti-bug: darkMode default é true, MAS só liga se o preset realmente carrega paletteDark — senão o toggle trocaria o data-theme sem tokens escuros atrás (render.ts:137–141). E com darkMode:false o documento é a marca LIGHT pura — "passes impeccable detect with zero findings" (render.ts:130–132) — sem NENHUMA maquinaria de toggle no HTML (render.ts:166–176).
Pense como… uma prensa tipográfica com uma única matriz de chumbo: troque a matriz (o preset) e TODA página futura muda junto; a página já impressa nunca muda sozinha. Onde a analogia quebra: esta prensa imprime duas edições da mesma matriz — a de arquivo (LIGHT, que o fiscal confere) e a de leitura (com o toggle) — e as duas saem da MESMA passada.
THEME_REGISTRY = { 'warm-neutral': WARM_NEUTRAL } (themes.ts:86–88); o próprio comentário marca skins alternativas como follow-up aditivo gated em gosto do founder (themes.ts:82–85). O plural do tipo existe; o catálogo, ainda não.O portão é curto e literal: o script raiz é "detect": "impeccable detect docs/*.html" (package.json:17) e o CI o roda como passo próprio — "Design gate (impeccable detect): pnpm detect" (.github/workflows/ci.yml:44–45). Repare no glob: docs/*.html pega os HTML do PRIMEIRO nível de docs/ — subpastas não entram no gate (o glob de um nível não desce; um HTML novo em docs/sub/ nasce FORA da governança até alguém promovê-lo).
E o pacote de design vigia a si mesmo: packages/design/src/impeccable-gate.test.ts resolve o binário com which impeccable (skip honesto se ausente), renderiza um renderHtmlPage(warm-neutral, darkMode:false) num tmp e exige detect --json ⇒ findings = [] — ZERO achados. O comentário do teste explica o porquê da variante LIGHT: "The detector is theme-naive (it statically pairs every declared text colour with every declared background, so a two-theme file shows false cross-theme low-contrast). It therefore governs the LIGHT brand only" (impeccable-gate.test.ts:40–44); o contraste do dark é verificado theme-aware em render.test.ts.
docs/ acumulou dezenas de findings e foi trazida a zero SEM afrouxar o detector: texto clay pequeno migrou para clay-ink #BE4019, o cinza de apoio para g500 #6B6A63, corpo mínimo ≥12px, títulos sem pular nível. A prova viva dessas escolhas está nos próprios tokens (themes.ts:14–15, :28, :35) e no fato de o CI rodar o gate a cada push (ci.yml:44–45).darkMode:false antes de exigir zero findings do impeccable?impeccable-gate.test.ts:40–44). Por isso o gate governa a marca LIGHT; o contraste dark é validado theme-aware em render.test.ts.alembic docs <src> <out> (CLI em apps/cli/src/commands.ts:4233–4266) valida que a origem é um diretório e chama generateSite (packages/docs/src/site.ts:62–94): varre a árvore RECURSIVAMENTE por .md/.markdown (site.ts:26–38), extrai o título do primeiro # heading (site.ts:40–43), converte cada arquivo com markdownToHtml, espelha a estrutura de pastas em .html e fecha com um index.html listando todas as páginas (site.ts:86–91).
O conversor (packages/docs/src/markdown.ts) cobre headings, parágrafos, listas, fenced code, inline code, bold/itálico e links — e é no link que mora a segurança: sanitizeUrl é um allow-list de schemes (http:, https:, mailto:; relativo/âncora passa) e TUDO mais vira '#'. A defesa é mais funda que um startsWith: caracteres fora do ASCII imprimível são STRIPADOS antes da detecção de scheme, porque o browser os ignora dentro de um scheme — jAvAsCrIpT:, java\tscript: e variantes com newline embutido colapsam todos em '#' (markdown.ts:9–27).
.md malicioso traz [click](jAvA\tScRiPt:alert(1)). O que o site gerado exibe no href?sanitizeUrl remove tudo fora de [!-~] ANTES de detectar o scheme (o browser ignora esses chars dentro de um scheme, então java\tscript: executaria!), baixa para minúsculas e só deixa passar http/https/mailto — o resto vira '#' (markdown.ts:9–27).A prova de que o tema-como-dado paga o preço da abstração está em quem o importa: packages/coda/src/course.ts — o gerador do curso visual-teach de alembic course — renderiza suas páginas SOBRE @alembic/design (prova: grep -rln '@alembic/design' packages/*/src apps/*/src lista coda/src/course.ts, contracts/src/theme.ts e a CLI). Ou seja: produto e cursos saem da MESMA função pura, do MESMO preset — quando um token muda no doc vivo, muda em TUDO que renderiza, e o gate confere.
| Consumidor | O que usa | Efeito |
|---|---|---|
coda/course.ts | renderHtmlPage + WARM_NEUTRAL | curso byte-estável com a cara da casa |
contracts/theme.ts | themePresetSchema | a FORMA do preset é contrato público |
apps/cli | design + docs (runDocs) | alembic course · alembic docs |
CI (pnpm detect) | o artefato em docs/*.html | governança a cada push (ci.yml:44–45) |
design é 100% puro (zero IO — render.ts:4–7) e docs é o oposto deliberado: generateSite lê e escreve disco diretamente (site.ts:62–94) — é uma ferramenta de build, não código de biblioteca do motor; seu único importador é a própria CLI (prova: grep -rln '@alembic/docs' packages/*/src apps/*/src).Verificação $0 da dupla e do gate:
# os tokens verbatim + a regra de proveniência do tema sed -n '9,40p;59,76p' packages/design/src/themes.ts # o renderer puro e a trava darkMode-exige-paletteDark sed -n '124,148p' packages/design/src/render.ts # o gate: script raiz, passo de CI e o teste que exige zero findings grep -n '"detect"' package.json grep -n -A1 'Design gate' .github/workflows/ci.yml sed -n '36,75p' packages/design/src/impeccable-gate.test.ts # rodar o gate localmente (read-only; exit 0 = suíte verde) pnpm detect # gerar um site de docs a partir de qualquer pasta de .md alembic docs docs/agents /tmp/agents-site --title "Agent docs" # o sanitizador de URL e suas evasões cobertas sed -n '9,27p' packages/docs/src/markdown.ts
clay-ink #BE4019 e g500 #6B6A63 existem POR CAUSA do detector — contraste AA calibrado no token (themes.ts:28, :35).renderHtmlPage é puro e emite dois artefatos: LIGHT gate-clean (zero findings, provado por teste) e o shell com toggle dos cursos (render.ts:130–141).impeccable detect docs/*.html — glob de um nível, subpastas fora (package.json:17; ci.yml:44–45).docs gera site recursivo com sanitizeUrl allow-list — javascript: e evasões colapsam em '#' (markdown.ts:9–27).docs/*.html, o que garante a qualidade de um HTML novo em docs/sub/?" — hoje, nada além de disciplina: promova-o ao primeiro nível ou estenda o glob. Próxima lição: a dupla de OBSERVAR o motor rodando — TUI ASCII no terminal, cockpit web sobre os run-dirs e o servidor HTTP+SSE do harness.