Skip to content

feat(regua): a unidade de medida passa a ser a aula, e os numeros vem da fonte unica - #70

Merged
alexandrebrt14-sys merged 2 commits into
mainfrom
feat/sincroniza-fonte-aula-20260827
Aug 28, 2026
Merged

feat(regua): a unidade de medida passa a ser a aula, e os numeros vem da fonte unica#70
alexandrebrt14-sys merged 2 commits into
mainfrom
feat/sincroniza-fonte-aula-20260827

Conversation

@alexandrebrt14-sys

Copy link
Copy Markdown
Owner

Os cursos gerados saíam rasos: apresentavam o conceito e não o explicavam. A causa não era o modelo, era a régua. O gate media módulo com piso de 2.500 palavras e uma bateria de pisos, e o prompt dava cota de palavras por parte. Cota se cumpre com abrangência, não com explicação: o redator listava seis conceitos em vez de explicar um.

Este PR aplica a seção ### curso-factory do PLANO_DE_MIGRACAO.md da fonte única de estilo (alexandrebrt14-sys/escrita-empreendedor, hash a10ed133921bd8f3f270a9980db43fe41ee05608bc5204b40dfd4b03f6f102b5).

Antes e depois

Regra Antes Depois
Unidade de medida módulo aula (tipo D da fonte)
Palavras piso 2.500 · alvo 3.000-4.000 · aviso acima de 4.500 piso 900 · alvo 1.200-2.400 · aviso 2.400 · erro 3.600
Cabeçalhos "ao menos 3 subtítulos", sem dizer o nível 2 a 4 H2; até 2 H3 por H2
Exercícios mínimo 3 por módulo (erro) 1 por aula, o "faça agora" de 5-15 min
Tabela mínimo 1 por módulo (erro) sem piso; entra quando substitui texto
Blockquote mínimo 1 por módulo (erro) sem piso
Blocos visuais piso de 3 por módulo, 1 a cada 2.500 caracteres teto de 3 por aula, só quando substituem texto
Estatísticas 5+ por módulo sem piso; entram quando respondem à pergunta do exemplo
Fontes 3+ por módulo 1 datada por trilha, no rodapé
Cápsula 18-75 palavras por seção 1 por trilha
Parágrafo até 8 linhas 15 a 45 palavras
Cota no prompt 250-350 / 800-1.200 / 400-600 / 200-250 palavras por parte sem cota por parte; 1.200-2.400 na aula, 60% explicar e 40% fazer
Onde os números moram YAML + constante em código + literal na mensagem de erro só em config/lexicos.json, espelho gerado da fonte
Clichês 18 em código + 56 no YAML (21 duplicadas) fonte + 35 específicos do repo + 13 de fallback, unidos em runtime

Compatibilidade. O pipeline ainda entrega "módulo", então check_content(..., unidade="modulo") mede a peça como 4 a 6 aulas: 4.800-14.400 palavras, piso 3.600, erro 21.600. QualityGate.check_text usa unidade="modulo" por padrão para não reprovar o acervo; quando o gerador emitir aula, o chamador passa unidade="aula". Está documentado no docstring de check_content e de tetos_da_unidade.

Um número só por regra. config/lexicos.json sai de python -m escrita.cli lexicos --json rodado na fonte e nunca é editado à mão. content_checker lê os tetos dali e interpola o valor carregado na mensagem de erro, em vez de repetir um literal — código, configuração e mensagem não conseguem mais divergir. As constantes FALLBACK_* só entram se o espelho sumir, para que uma configuração corrompida não desligue o gate em silêncio.

Arquivos

Arquivo O que mudou
config/lexicos.json novo. Espelho gerado da fonte: tetos por tipo de página e as cinco listas de expressão vetada
src/validators/lexicos_loader.py novo. Lê o espelho em runtime; tetos_da_aula() e expressoes_vetadas(). Nunca levanta exceção
src/validators/content_checker.py unidade AULA; tetos_da_unidade() com o modo de compatibilidade; extensão, H2, H3/H2, teto de visuais, 1 exercício; parágrafo em palavras; FORBIDDEN_CLICHES podado para 13; poda de substring nas expressões vetadas
src/validators/quality_gate.py check_text/check_html ganham unidade, padrão "modulo", com o motivo no docstring
src/validators/voice_guard.py teto de parágrafo em palavras, importado do content_checker
config/quality_rules.yaml content_quality reescrito: só o que é específico do repo (aulas por trilha, exercício por aula, fonte por trilha); as 21 expressões que a fonte já cobria saíram; nota de unidade em visual_density
src/templates/prompts/draft.md e pt-br/draft.md estrutura de aula do molde D nas duas partes; 1.200-2.400 palavras pedidas explicitamente, "menos de 900 é raso"; sem cota por parte; teto de 3 apoios visuais
src/orchestrator.py o prompt de redação deixa de mandar "2.500-4.000 palavras" e a sequência de seis partes com cota
docs/GOVERNANCA_PUBLICACAO_CURSO.md "nunca mais que 2 blocos text seguidos sem um visual" vira "até 3 visuais por aula, só quando substituem texto"
DIRETRIZ_EDITORIAL.md vira ponteiro (hash-fonte + sincronizado-em), guardando só o motor de cursos, o teto de 1.200 caracteres de renderização e a linha de base do acervo
GUIA_ESCRITA_HUMANIZADA.md vira ponteiro; a bibliografia datada desceu para docs/research/HUMANIZACAO_AI_ESTADO_DA_ARTE_2026.md
tests/test_regua_aula.py novo. 19 testes: espelho, modo módulo, extensão, estrutura, parágrafo
tests/test_validators_smoke.py, tests/test_voice_guard.py dois testes que fixavam o comportamento antigo, ajustados com o motivo no docstring
docs/TRIAGEM_PRS_20260827.md novo. Triagem dos 16 PRs abertos (recomendação, nada foi fechado)
output/ sai do índice do Git (7 rascunhos gerados, já cobertos pelo .gitignore)

Testes

python -m pytest -q
369 passed, 1 skipped, 81 subtests passed in 4.50s

Dois testes existentes precisaram mudar, e os dois por causa da mudança:

  • test_cliche_usa_fallback_quando_yaml_nao_carrega afirmava que, sem o YAML, "especialistas apontam" deixava de ser checado. Com o espelho da fonte a cobertura não depende mais do YAML do repo, então o teste passou a afirmar o contrário (e foi renomeado).
  • test_anti_cliche_one_offence caiu de 75 para 50 porque "em um mundo cada vez mais" contém o conectivo "cada vez mais" e o mesmo trecho era cobrado duas vezes. A correção foi no código (poda de substring em _check_cliches), não no teste, e o teste agora documenta a armadilha.

Triagem de PRs (nenhum foi tocado)

16 PRs abertos: 5 para mergear (#65, #62, #58, #56, #52), 5 para fechar como superados (#42, #35, #28, #26, #21), 5 para rebase (#61, #36, #34, #27, #1) e 1 para manter (#43). Evidência por PR em docs/TRIAGEM_PRS_20260827.md.

O que ficou de fora

  • src/templates/page.tsx.j2 (blocos fixos por trilha, paginação, barra de progresso por trilha) não entrou: é o motor de renderização e mexer nele junto com a régua misturaria duas mudanças com riscos diferentes.
  • editorial.words_per_module_min/max em config/clients/*/client.yaml continua com os números antigos. É configuração morta: carregada por loader.py, nunca consumida. Vale apagar num PR de limpeza.
  • en/draft.md e es/draft.md seguem com a estrutura antiga. O teste de espelho de idioma cobre só pt-br contra a raiz, e traduzir a nova estrutura é trabalho editorial próprio.

🤖 Generated with Claude Code

alexandrebrt14-sys and others added 2 commits August 27, 2026 21:44
… da fonte única

Os cursos gerados saíam rasos: apresentavam o conceito e não o explicavam. A
causa era a régua, não o modelo. O gate media MÓDULO com piso de 2.500 palavras
e uma bateria de pisos (3+ exercícios, 5+ estatísticas, 3+ fontes, 1+ tabela,
1+ blockquote, 3+ blocos visuais), e o prompt dava cota de palavras por parte.
Cota se cumpre com abrangência, não com explicação.

A unidade agora é a AULA (tipo D da fonte de estilo escrita-empreendedor,
hash a10ed133): piso 900, alvo 1.200-2.400, aviso 2.400, erro 3.600 palavras;
2 a 4 H2; até 2 H3 por H2; até 3 apoios visuais; parágrafo de 15 a 45 palavras;
1 exercício por aula; 1 fonte datada e 1 cápsula por trilha.

Nenhum número da régua mora mais neste repositório. config/lexicos.json é
espelho gerado da fonte e lexicos_loader.py o lê em runtime; content_checker
interpola o valor carregado na mensagem de erro, então código, configuração e
mensagem não conseguem divergir.

Compatibilidade: check_content(..., unidade="modulo") mede a peça como 4 a 6
aulas (4.800-14.400 palavras), que é o que o pipeline ainda entrega.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nenhum PR foi fechado, mergeado ou rebaseado: o arquivo é recomendação com
evidência por PR (arquivo já em main, tamanho do arquivo em main contra o do
branch, ancestralidade do commit).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alexandrebrt14-sys
alexandrebrt14-sys merged commit 9cef834 into main Aug 28, 2026
7 checks passed
@alexandrebrt14-sys
alexandrebrt14-sys deleted the feat/sincroniza-fonte-aula-20260827 branch August 28, 2026 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant