Intake: req-127.md
Validação: VALIDATION-CHECKLIST.md#batch-129
Status: implemented-pending-homologation
O Assistente de IA recebia {{html}}, {{css}} e {{framework_css}} — e {{framework_css}} é a
string tailwindcss, que não diz nada sobre a marca do projeto. O modelo respondia com bg-red-600
onde o projeto tem bg-mp-red, e o operador reescrevia a mão a cada interação. Mandar o
browser-contract.css bruto resolveria o problema e custaria 78 KB (~20 mil tokens) por interação.
Este lote entrega o meio-termo: um extrator que devolve ~1,5 KB com as declarações do @theme que
viram utility e os nomes das classes de @layer components.
Atividades Técnicas
-
[x] Extrator semântico (
gestor/bibliotecas/html-editor.php):-
html_editor_ia_extrair_tokens_tema(?string $caminhoContrato = null, ?int $limiteBytes = null)resolve o contrato pelo mesmo caminho do runtime do Tailwind Browser (html_editor_tailwind_browser_contract(), req-114/req-117):contents/do projeto na frente deassets/do core. -
html_editor_ia_tokens_tema_compilar()é a parte PURA (string entra, string sai) — a mesma separação do parhtml_editor_css_precompiled_concatenar()/..._baseline()do req-117. -
Auxiliares:
..._limite()(orçamento),..._namespaces()(allowlist),..._valor_util()(corte por forma do valor),..._bloco()(recorte balanceado do@theme),..._componentes()(classes de@layer components).
-
-
[x] Injeção no payload (
html_editor_ajax_ia_requests):-
html_editor_ia_modo_theme_tokens_aplicar()troca{{theme_tokens}}e retira os marcadores; o bloco INTEIRO sai quando não há contrato. -
{{css_compiled}}opt-in, resumido porhtml_editor_ia_css_classes_resumir().
-
-
[x] Modos de IA (fonte em
resources/, não no JSON compilado):-
Diretriz adicionada nos 6
.md:paginas,paginas-editbar(admin-paginas) ecomponentes(admin-componentes), empt-breen. -
versionde1.0para1.1nosai_modesdos dois módulos;ModosIaData.jsonrecompilado porc2f resources:sync.
-
-
[x] Testes:
-
tests/Unit/PHP/HtmlEditorIaThemeTokensTest.php(39 casos) — extrator e bloco condicional. -
tests/Integration/HtmlEditorIaRequestsThemeTokensTest.php(11 casos) — payload real do endpoint nos três escopos de edição, com dublê deia_enviar_prompt().
-
Decisões tomadas na implementação
-
A ordem de corte é round-robin entre namespaces, não sequencial. Medido no
[REDACTED]: 63 cores contra 3--shadow-*. Na varredura sequencial as cores consomem o orçamento inteiro e o outro namespace do contrato some por ser pequeno. Uma rodada por namespace resolve, e a saída volta à ordem natural — o round-robin decide QUEM entra, nunca em que ordem sai. -
O corte de valor é por FORMA, não por nome. Qualquer valor com
data:,url()longo ou mais de 120 bytes cai fora. Contrato futuro que embuta asset cai na mesma regra sem allowlist nova. É o que tira as--art-*-maskdo[REDACTED](uma só passa de 700 bytes e não vira utility). -
A allowlist de namespaces vai além dos três do intake. O intake cita
--color-*,--font-*e--spacing-*; entraram também--text-,--radius-,--shadow-,--breakpoint-,--container-,--leading-e--tracking-, porque todos viram utility com nome próprio no v4 e sem eles a IA escreve o valor arbitráriorounded-[12px]em vez do token da marca. Medido: nos quatro contratos do ambiente local esses namespaces somados não passam de 10 declarações. -
A diretriz é bloco condicional, com o par de marcadores da convenção do core. Projeto sem contrato, ou fora do Tailwind, tem a seção inteira removida por
modelo_tag_del(). Mandar o modelo "usar prioritariamente" uma lista que chega em branco é pior do que não mandar nada — ele preenche a lacuna inventando. -
A frase-guia fica no
.md, não no PHP. O bloco injetado é CSS puro; a instrução que ensina a derivar a utility do token (--color-mp-red→bg-mp-red) é texto de produto e vive no artefato multi-idioma. Sem ela o modelo escrevestyle="color: var(--color-mp-red)", que funciona e não é o que o projeto usa. -
{{css_compiled}}é opt-in e resumido. O valor cru é o output inteiro do Tailwind e devolveria o payload à casa dos 20 mil tokens. Nenhum modo do core declara a tag; ela existe para o operador que quiser o contexto num modo próprio. As utilities do v4 escapam o seletor (.lg\:flex), e o resumo desescapa — é o nome desescapado que vai no atributoclass.
Findings do review, corrigidos nesta rodada
Dois casos do próprio lote, ambos no caminho "projeto sem contrato de tema". O modo de IA é editável no painel e vive no banco, então nem os marcadores nem a tag podem ser tratados como garantidos:
-
Tag sem marcadores vazava literal. Modo em que o operador apagou o par mas manteve
{{theme_tokens}}:modelo_tag_del()não encontrava o que cortar e a tag saía escrita por extenso dentro do bloco```cssdo payload. A troca por vazio passou a acontecer sempre, depois do corte. -
Marcador invertido cortava do lugar errado.
modelo_tag_del()opera por posição: com> -->antes de< -->, o corte levaria o resto do prompt junto. Passou a haver guard de ordem ($pos_in < $pos_out) antes de chamar a função.
Cobertos por testTagSemMarcadoresNaoVazaLiteralQuandoNaoHaTokens,
testMarcadorInvertidoNaoLevaORestoDoPromptJunto e testTagSemMarcadoresAindaRecebeOsTokens.
Fora do escopo (registrado, não corrigido)
-
versaodeai_modeseai_promptsnunca incrementa. Emgestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php,carregarDadosExistentes()indexa os existentes sob as chavesmodos_ia/prompts_ia, masversaoChecksumPrompt()é chamada com'ai_modes'/'ai_prompts'— oisset($existentes[$tipo][$key])é sempre falso e a versão fica em1para sempre. Não bloqueia este lote: o sync do banco decide o que atualizar pelo md5 do arquivoModosIaData.jsone faz UPSERT campo a campo, emodos_iatempreserve_on_user_modified: [], então o prompt novo chega ao banco de qualquer forma. Corrigir incrementaria a versão dos 24 modos e 32 prompts de uma vez, o que é ruído fora deste lote. -
{{html_extra_head}}nunca é substituída no payload. O modocomponentes(pt-br e en) declara a tag num bloco```html-extra-head, mashtml_editor_ajax_ia_requests()só troca{{html}},{{css}}e{{framework_css}}— a tag chega ao modelo escrita por extenso. É defeito pré-existente e não é one-liner:iaRequestsData()emhtml-editor-interface.jsnão envia o campo, então corrigir de verdade significa mexer também no front. Fora do escopo do req-127, que trata de contexto de tema; registrado aqui para o próximo lote que tocar o Assistente.