BATCH-054 - Ajustes Visuais de Margem e Tooltip com Detalhe de Perfis no Módulo Menus (req-054)
-
[x] Ajuste de Margem nas Tags:
-
[x] Margem aplicada às tags de perfis selecionados (
#condition-profile-tags/.condition-profile-tag) para garantir espaçamento adequado em relação aos botões do formulário.
-
-
[x] Abas de Condição com Contador e Tooltip:
-
[x] Abas de condição
perfil_usuarioexibem contadorslug (Perfil de usuário - N). -
[x] Abas recebem tooltip Fomantic-UI formatado (
Usuário Perfis: Perfil 1, Perfil 2...) com os nomes legíveis dos perfis. -
[x] Fallback automático para os IDs se os nomes/labels dos perfis não estiverem salvos.
-
Evidência de Validação (BATCH-054)
Evidência automatizada reportada pelo executor em 2026-06-22:
-
Linting estático:
-
php -l gestor\modulos\menus\menus.php→ OK -
php -l gestor\modulos\menus\menus.widget.php→ OK -
node --check gestor\modulos\menus\menus.js→ OK
-
-
Verificação de diff:
git diff --checkpassou limpo nos arquivos do lote.
Pendências Runtime
-
Sincronizar os recursos via
Update => Core. -
Validar visualmente no navegador que as tags do CRUD possuem espaçamento inferior e não encostam no botão de confirmação.
-
Validar que ao passar o mouse nas abas das condições, o tooltip do Fomantic-UI renderiza o nome legível dos perfis vinculados e o título exibe o número de itens selecionados.
BATCH-056 - Sincronização Declarativa de Recursos, Deleção e Atualização Forçada (req-056)
-
[x] Gerador (
atualizacao-dados-recursos.php):-
[x]
normalizarConfigTabela()aceitaconfigobjeto OU array de objetos (objeto → array de 1); resolvetabela_nome; agregadeletar/forcar_atualizacaopor elemento e por bloco (retrocompat). -
[x]
coletarConfigsTabelas()(motor compartilhado) reaproveitado porgerarSchemaMetadata()ecoletarRecursos(). -
[x]
gerarSchemaMetadata()consolidadeletare novoforcar_atualizacao(mapas de topo) noschema-metadata.json; campos de varredura ficam fora do contrato. -
[x] Varredura
sync_resources:lerMetadadosDinamicos()(externo/inline por idioma),processarRegistroDinamico()(field_typesjson/file:<ext>, BOM removido, colunas padronizadas),checksumRegistroDinamico()(reuso de versão). -
[x]
atualizarDados()gera<PascalCase>Data.jsondinâmico viadataFileNameFromTable(), pulando as 9 tabelas fixas reservadas.
-
-
[x] Config global (
tables_config.json):_commentestendido (config objeto/array,tabela_nome,sync_resources/resources_dir/metadata_file/field_types/deletar/forcar_atualizacao); 4 tabelas existentes mantidas (retrocompat). -
[x] Atualizador (
atualizacoes-banco-de-dados.php):schemaMetadata()lêforcar_atualizacao;forcarAtualizacaoLista()+$isForced(); bypass deproject/user_modified+ resetuser_modified=0+ preservação deprojectnos 3 caminhos (PK, chave natural, fallback). Correção${var}→{$var}(deprecation PHP 8.4). -
[x] Documentação: 6 docs × pt-br/en atualizados (Recursos, Atualizações, Módulos Detalhado, Módulos Overview, Multilíngue, Proteção de Banco).
Evidência de Validação (BATCH-056)
Evidência automatizada reportada pelo executor em 2026-06-23 (ambiente: PHP 8.4.8, mbstring/pdo_sqlite/pdo_mysql):
-
php -l gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php→ OK -
php -l gestor/controladores/atualizacoes/atualizacoes-banco-de-dados.php→ OK -
json_decodedegestor/resources/tables_config.json→ VALID -
Regeneração do contrato via
SDD_NO_AUTORUN+gerarSchemaMetadata()→ 17 tabelas preservadas, chave de topoforcar_atualizacaopresente (vazia, pois nada declara ainda). -
Smoke da varredura dinâmica (fixtures temporárias):
file:html/file:csscom BOM removido,field_types: jsoncodificado, injeção delanguage/status/module, checksum estável e sensível a mudança de arquivo, leitura inline e externa → OK. -
Teste de regressão
tests/Unit/PHP/ForcarAtualizacaoTest.php(PDO SQLite + contrato temporário): forçado por chave natural (payload completo +user_modified→0,projectpreservado), forçado por PK (bypass deproject), preservação normal deuser_modified=1, proteção de projeto →updated=2,same=2, todas as asserts PASS. -
composer test(suíte completa) → 48 testes, 142 assertions, OK (4 skipped = testes de banco gated; 1 PHPUnit deprecation pré-existente, não relacionada).
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Core(regeneraschema-metadata.json+<Pascal>Data.jsondinâmicos e recalcula checksums) e validar a sincronização em MySQL. -
Validação manual end-to-end do
forcar_atualizacaoem MySQL: configurar uma tabela com registro emforcar_atualizacao, marcaruser_modified=1no banco, rodar o deploy e confirmar que o dado físico foi reintegrado euser_modifiedvoltou a0.
BATCH-057 - Correção de Tipagem e Validação de Perfil Anônimo em Menus Condicionais (req-057)
-
[x] Normalização de perfil anônimo em array (converter para
falseseidfor'_anonimo'ouid_usuariosfor0). -
[x] Obtenção de profile ID sem warnings (ler
$params['_profile_slug']ouid_usuarios_perfisquando$perfil_usuariofor array). -
[x] Validação estática (
php -l) no arquivogestor/modulos/menus/menus.widget.phpsem erros. -
[x] Suíte de testes
tests/Unit/PHP/MenusWidgetConditionalVisibilityTest.phpexecutada sem falhas ou warnings.
Evidência de Validação (BATCH-057)
-
Validação estática e de testes executada em 2026-06-24:
-
php -l gestor/modulos/menus/menus.widget.php→No syntax errors detected. -
Baseline (antes da correção):
MenusWidgetConditionalVisibilityTest→ 2 falhas (testRenderizaMenuPublicoParaUsuarioAnonimo,testRenderizaMenuDePerfilQuandoIdEstaEntreMultiplosPerfisPermitidos) + 1 PHP warning (Array to string conversionemmenus.widget.php:288). -
Pós-correção:
vendor/bin/phpunit tests/Unit/PHP/MenusWidgetConditionalVisibilityTest.php→ OK (7 tests, 19 assertions), sem falhas e sem warnings. -
Suíte PHP completa (
composer test) → OK (48 tests, 142 assertions, 4 skipped gated por banco), sem novas falhas (a únicaPHPUnit Deprecationé pré-existente e alheia a este slice).
-
-
Arquivo alterado:
gestor/modulos/menus/menus.widget.php(apenas a funçãomenus_widget_condicao_valida). -
Decisão registrada: DEC-065.
-
Observação de escopo: o intake (req-057) cita "9 testes", mas a suíte real
MenusWidgetConditionalVisibilityTestcontém 7 testes — todos passam. Nenhum teste novo foi criado, pois o req descreve apenas a correção do widget; a divergência de contagem foi registrada para rastreabilidade. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-058 - Sistema de Recuperação e Engenharia Reversa de Recursos (Pull System) (req-058)
-
[x] Endpoint
_api/project/recoverimplementado emgestor/controladores/api/api.phpcom validação OAuth e compressão ZIP. -
[x] Novo orquestrador CLI de exportação
gestor/controladores/recuperacoes/recuperacao-dados-recursos.phpno servidor. -
[x] Novo descompilador genérico
gestor/controladores/agents/arquitetura/recuperacao-dados-recursos.phpno cliente local. -
[x] Script de pull
ai-workspace/en/scripts/projects/recover-project.shintegrado às VS Code Tasks. -
[x] Remoção de BOM e saneamento de metadados (
versao,checksum,user_modified,projecte chaves PK/auto-incremento) validados. -
[x] Suíte de testes unitários
tests/Unit/PHP/RecuperacaoDadosRecursosTest.phpcobrindo a engenharia reversa inline/externa de HTML/CSS/JSON. -
[x] Validação estática (
php -l) de todos os arquivos PHP gerados. -
[ ] Validação manual end-to-end de pull local e git status limpo. (pendente com o operador — requer API rodando + token OAuth do projeto)
Evidência de Validação (BATCH-058)
Evidência automatizada reportada pelo executor em 2026-06-25 (ambiente: PHP 8.4.8, mbstring/pdo_sqlite/pdo_mysql):
-
Linting estático (
php -l) → OK (4/4):-
gestor/controladores/api/api.php -
gestor/controladores/recuperacoes/recuperacao-dados-recursos.php -
gestor/controladores/agents/arquitetura/recuperacao-dados-recursos.php -
tests/Unit/PHP/RecuperacaoDadosRecursosTest.php
-
-
Sintaxe bash (
bash -n) doai-workspace/en/scripts/projects/recover-project.sh→ OK; script tornado executável (chmod +x). -
.vscode/tasks.jsonrevalidado como JSON válido após inserir as tarefas?️ Projects - Recover Current Projecte?️ Projects - Recover Project -> ID. -
Teste novo
tests/Unit/PHP/RecuperacaoDadosRecursosTest.php→ OK (6 tests, 44 assertions): extraçãofile:<ext>em layout PLANO com BOM removido, decodificação de campojson, saneamento deversao/checksum/user_modified/project/PK/language/status='A'/módulo-dono, escrita externa (global semresources_dir→<lang>/<tabela>.json) e inline (resources->idioma->tabelapreservando o restante do JSON raiz), e resolução de caminhos (global com/semresources_dir, módulo). -
Smoke manual do descompilador com fixtures sintéticas (round-trip):
fields_schema(json) decodificado para objeto aninhado,htmlextraído pararesources/pt-br/widgets_demo/hero.htmlsem BOM e metadado externo saneado. OK. -
Suíte PHP completa (
composer test) → OK (54 tests, 186 assertions, 4 skipped gated por banco); a únicaPHPUnit Deprecationé pré-existente e alheia a este slice.
Pendências Runtime (com o operador)
-
Rodar a task
?️ Projects - Recover Current Project(ou-> ID) contra um projeto com API ativa e token OAuth válido; confirmar download do ZIP, descompilação dos recursos e recompilação consistente. -
Verificar no Git que as alterações feitas no banco (painel admin) foram trazidas para os arquivos de recursos (globais e de módulos) com
git statuslimpo de ruído (sem colunas de build). -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-059 - Refinamentos, Overrides de Projeto e Sincronização Inteligente de Contents (req-059)
-
[x] Script CLI do servidor renomeado para
gestor/controladores/recuperacoes/recuperacao-banco-de-dados.php. -
[x] Compilador e descompilador de recursos suportando overrides de
scopeemoduloemtables_config.json. -
[x] Endpoint
_api/project/recovercompactando opcionalmente o diretóriogestor/contents/sob o caminhocontents/no ZIP. -
[x] Descompilador realizando pull inteligente da pasta
contents/comparando MD5 e timestamps, e aplicandotouch(). -
[x] Relatório de conflito exibido no final do pull mostrando alertas de choque no padrão
RDR_CONFLITOpara arquivos modificados localmente que são mais recentes que a versão alterada do servidor. -
[x] Script
recover-project.she VS Code Tasks atualizados com a flag--contents. -
[x] Suíte de testes
RecuperacaoDadosRecursosTest.phpestendida para cobrir overrides emtables_config.json, comparação MD5 e timestamps (conflito/choque) no pull decontents. -
[x] Validação estática (
php -l) de todos os arquivos PHP alterados.
Evidência de Validação (BATCH-059)
Evidência automatizada reportada pelo executor em 2026-06-25:
-
Linting estático (
php -l) OK:-
gestor/controladores/api/api.php -
gestor/controladores/recuperacoes/recuperacao-banco-de-dados.php -
gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php -
gestor/controladores/agents/arquitetura/recuperacao-dados-recursos.php -
tests/Unit/PHP/RecuperacaoDadosRecursosTest.php
-
-
.vscode/tasks.jsonvalidado porConvertFrom-Json: 46 tasks. -
git diff --checkOK. -
vendor/bin/phpunit tests/Unit/PHP/RecuperacaoDadosRecursosTest.phpOK: 11 tests, 65 assertions. -
composer testOK: 59 tests, 207 assertions; 4 skipped gated por banco; 1PHPUnit Deprecationpreexistente. -
bash -n ai-workspace/en/scripts/projects/recover-project.shnão executado: neste Windows o comandobashencaminha para WSL, mas não há distribuição instalada.
Pendências Runtime (com o operador)
-
Executar a task
?️ Projects - Recover Current Project with Contentscontra API ativa e token OAuth válido. -
Confirmar manualmente que conflitos reais em
contents/aparecem comoRDR_CONFLITO/RDR_CONFLITOSsem sobrescrever arquivos locais mais recentes.
BATCH-060 - Pipeline de Metadados de Projeto e Desacoplamento (req-060)
-
[x] Compilador gerando
project-schema-metadata.jsonna raiz do gestor local a partir detables_config.json. -
[x] Script de deploy
deploy-project-v2.shincluindogestor/project-schema-metadata.jsonno empacotamento do ZIP de release. -
[x] Endpoint da API
_api/project/recoverno servidor lendo as tabelas doproject-schema-metadata.jsonpara o dump. -
[x] Script CLI do servidor
recuperacao-banco-de-dados.phplendo as tabelas doproject-schema-metadata.json. -
[x] Documentação em português
ai-workspace/pt-br/docs/CONN2FLOW-SISTEMA-RECURSOS.mdatualizada com o funcionamento doproject-schema-metadata.jsone exemplos completos de configuração dotables_config.json. -
[x] Validação estática (
php -l) de todos os arquivos PHP alterados. -
[x] Suíte de testes
RecuperacaoDadosRecursosTest.phpe compilação válidas.
Evidência de Validação (BATCH-060)
Evidência automatizada reportada pelo executor em 2026-06-25:
-
php -lOK:-
gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php -
gestor/controladores/api/api.php -
gestor/controladores/recuperacoes/recuperacao-banco-de-dados.php -
tests/Unit/PHP/RecuperacaoDadosRecursosTest.php
-
-
vendor/bin/phpunit tests/Unit/PHP/RecuperacaoDadosRecursosTest.phpOK: 13 tests, 71 assertions. -
composer testOK: 61 tests, 213 assertions; 4 skipped gated por banco; 1PHPUnit Deprecationpreexistente. -
git diff --checkOK. -
bash -n ai-workspace/en/scripts/projects/deploy-project-v2.shnão executado: neste Windows o comandobashencaminha para WSL, mas não há distribuição instalada.
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Deploy Current Projectou-> IDem ambiente com Bash/7z disponível e confirmar queproject-schema-metadata.jsonchega ao servidor. -
Rodar o pull contra API ativa sem
tablesexplícito e confirmar que tabelas declaradas apenas no manifesto de projeto entram no ZIP de recuperação.
BATCH-061 - Renomeação para project_tables_config.json e Filtragem de Manifesto (req-061)
-
[x] Configuração customizada do projeto renomeada logicamente para
gestor/resources/project_tables_config.json. -
[x]
gestor/resources/tables_config.jsonpreservado como arquivo global do core. -
[x] Compilador em modo
--project-pathlendo core detables_config.jsone projeto deproject_tables_config.json. -
[x]
project-schema-metadata.jsonfiltrado para conter apenas tabelas declaradas emproject_tables_config.json. -
[x] Descompilador lendo
tables_config.jsoneproject_tables_config.jsonem ordem, com o arquivo de projeto sobrescrevendo configs globais. -
[x] Documentação pt-br/en atualizada para o novo nome do arquivo de projeto.
-
[x] Testes atualizados para simular
project_tables_config.json. -
[x] Validação estática (
php -l) de todos os PHP alterados.
Evidência de Validação (BATCH-061)
Evidência automatizada reportada pelo executor em 2026-06-25:
-
php -lOK:-
gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php -
gestor/controladores/agents/arquitetura/recuperacao-dados-recursos.php -
tests/Unit/PHP/RecuperacaoDadosRecursosTest.php
-
-
vendor/bin/phpunit tests/Unit/PHP/RecuperacaoDadosRecursosTest.phpOK: 13 tests, 72 assertions. -
composer testOK: 61 tests, 214 assertions; 4 skipped gated por banco; 1PHPUnit Deprecationpreexistente. -
git diff --check -- . ':(exclude)sdd/human-requests/CURRENT.md'OK. Ogit diff --checkcompleto acusa linha em branco final emsdd/human-requests/CURRENT.md, arquivo de intake humano já alterado antes da execução e não editado pelo executor.
Pendências Runtime (com o operador)
-
Em um projeto real, renomear/mover configurações customizadas de
resources/tables_config.jsonpararesources/project_tables_config.json. -
Rodar
Update => Core/deploy em modo projeto e confirmar queproject-schema-metadata.jsoncontém apenas as tabelas declaradas no arquivo de projeto.
BATCH-062 - Fallback de Idioma e Estruturação de Pastas de Recursos Dinâmicos (req-062)
-
[x] Descompilador usando fallback
pt-brpara registros semlanguageoulinguagem_codigo. -
[x] Compilador lendo arquivos físicos
file:<ext>em<resources_dir|tabela>/<id>/<id>.<ext>. -
[x] Descompilador escrevendo arquivos físicos
file:<ext>em<resources_dir|tabela>/<id>/<id>.<ext>. -
[x] Suíte
RecuperacaoDadosRecursosTest.phpcobrindo fallback de idioma e subpastas por ID. -
[x] Documentação pt-br/en atualizada para o novo layout físico.
-
[x] Validação estática (
php -l) de todos os PHP alterados.
Evidência de Validação (BATCH-062)
Evidência automatizada reportada pelo executor em 2026-06-25:
-
php -lOK:-
gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php -
gestor/controladores/agents/arquitetura/recuperacao-dados-recursos.php -
tests/Unit/PHP/RecuperacaoDadosRecursosTest.php
-
-
vendor/bin/phpunit tests/Unit/PHP/RecuperacaoDadosRecursosTest.phpOK: 15 tests, 78 assertions. -
composer testOK: 63 tests, 220 assertions; 4 skipped gated por banco; 1PHPUnit Deprecationpreexistente. -
git diff --check -- . ':(exclude)sdd/human-requests/CURRENT.md'OK. Ogit diff --checkcompleto ainda herda linha em branco final emsdd/human-requests/CURRENT.md, arquivo de intake humano já alterado antes da execução.
Pendências Runtime (com o operador)
-
Em projeto real, mover arquivos físicos dinâmicos existentes do layout plano para
<id>/<id>.<ext>. -
Rodar pull de tabela sem idioma, como
arquivos, e confirmar geração emresources/pt-br/.
BATCH-063 - Depuração e Logging Explicativo na Descompilação de Arquivos (req-063)
-
[x] Depuração de
arquivos=0:-
[x] Validar que quando arquivos dinâmicos (como de
galleries,menus,publisher) têm campos físicos (html,css) nulos ou vazios no banco/JSON de origem, a descompilação não gera arquivos físicos correspondentes no disco (comportamento esperado). Causa-raiz confirmada: registros que usam o template padrão sem customização gravamhtml/cssnulos no banco.
-
-
[x] Log de Depuração no Console:
-
[x] Log
RDR_DEBUG_FILE_EMPTY tabela=X id=Y campo=Zemitido (modo não silencioso) quando a gravação de um arquivo físico é pulada por campo nulo/vazio. A condição antiga (!== null) deixava passar string vazia e gerava arquivo em branco — agora qualquer conteúdo vazio (inclusive só-BOM) é omitido.
-
-
[x] Validação com Testes Unitários:
-
[x]
testCampoFileNuloOuVazioEmiteLogEnaoCriaArquivo: campos''/nulos não acumulam arquivo e emitem o log por campo. -
[x]
testProcessaMisturaCustomizadoEPadraoSemArquivoEmBranco: cenário misto (1 customizado gera 2 arquivos, 1 padrão gera 0 + log), metadados escritos para ambos, sem arquivo em branco no disco.
-
-
[x] Validação Estática:
-
[x]
php -lOK no descompilador e no teste.
-
Evidência de Validação (BATCH-063)
Evidência automatizada reportada pelo executor em 2026-06-25 (ambiente: PHP 8.4.8):
-
php -l gestor/controladores/agents/arquitetura/recuperacao-dados-recursos.php→ OK -
php -l tests/Unit/PHP/RecuperacaoDadosRecursosTest.php→ OK -
vendor/bin/phpunit tests/Unit/PHP/RecuperacaoDadosRecursosTest.php→ OK (17 tests, 97 assertions) (era 15; +2 deste lote). -
composer test→ OK (65 tests, 239 assertions, 4 skipped gated por banco); a únicaPHPUnit Deprecationé pré-existente e alheia a este slice. -
Arquivos alterados:
gestor/controladores/agents/arquitetura/recuperacao-dados-recursos.php(funçãordr_descompilar_registro+ docblock),tests/Unit/PHP/RecuperacaoDadosRecursosTest.php.
Pendências Runtime (com o operador)
-
Rodar o pull real (
?️ Projects - Recover ...) contra a API e confirmar queRDR_DEBUG_FILE_EMPTYaparece no console para os registros que usam template padrão e que nenhum arquivo em branco é criado emresources/. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-064 - Atualização de Versões dos Componentes do GitHub Actions (req-064)
-
[x] Atualização de
actions/checkout@v4paraactions/checkout@v7nos workflowsrelease-gestor.ymlerelease-instalador.yml. -
[x] Atualização de
actions/setup-node@v4paraactions/setup-node@v6emrelease-gestor.yml. -
[x] Atualização de
softprops/action-gh-release@v2parasoftprops/action-gh-release@v3nos dois workflows. -
[x] Validação estática de formato YAML em ambos os workflows.
Evidência de Validação (BATCH-064)
Evidência automatizada e estática reportada pelo executor em 2026-06-25:
-
Edições aplicadas aos arquivos:
.github/workflows/release-gestor.ymle.github/workflows/release-instalador.yml. -
Sintaxe YAML validada estaticamente. O teste final runtime ocorrerá no próximo disparo do pipeline via GitHub.
BATCH-065 - Suporte a Colunas Customizadas de ID em Recursos Dinâmicos (req-065)
-
[x] Descompilador (
recuperacao-dados-recursos.php):-
[x] Ler dinamicamente a coluna configurada em
$cfg['id']emrdr_descompilar_registro()para determinar o$id(helperrdr_id_col($cfg)com fallback'id'). -
[x] Ajustar o log
RDR_REGISTRO_SEM_LANGpara ler o ID de forma dinâmica na varredura.
-
-
[x] Compilador (
atualizacao-dados-recursos.php):-
[x] Ajustar a leitura de
$rec[$idCol]no laço principal de compilação dinâmica. -
[x] Ajustar a leitura de
$rec[$idCol]emprocessarRegistroDinamico(). -
[x] Ajustar o cache
$existDinamicoCachepara construir o índice de busca usando a coluna de ID dinâmica da tabela.
-
-
[x] Testes Unitários:
-
[x] Criar teste dinâmico simulando round-trip completo com tabela de ID customizado (
page_id/ PKid_publisher_pages). -
[x] Confirmar que
composer testpassa limpo.
-
-
[x] Validação Estática:
-
[x] Rodar
php -lsem erros.
-
Evidência de Validação (BATCH-065)
Evidência automatizada reportada pelo executor em 2026-06-25 (ambiente: PHP 8.4.8):
-
php -l→ OK (3/3):-
gestor/controladores/agents/arquitetura/recuperacao-dados-recursos.php -
gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php -
tests/Unit/PHP/RecuperacaoDadosRecursosTest.php
-
-
vendor/bin/phpunit tests/Unit/PHP/RecuperacaoDadosRecursosTest.php→ OK (19 tests, 113 assertions) (era 17; +2 deste lote). -
composer test→ OK (67 tests, 255 assertions, 4 skipped gated por banco); a únicaPHPUnit Deprecationé pré-existente e alheia a este slice. -
Testes novos:
-
testDescompilaResolveColunaIdCustomizada: dump compage_id(sem colunaid) gera o arquivo emresources/pt-br/publisher_pages/sobre/sobre.html, preservapage_idno metadado e remove a PKid_publisher_pages. -
testRoundTripColunaIdCustomizada(RunInSeparateProcess): descompilaPublisherPagesData.json(page_id) para arquivo físico + metadado e recompila viaprocessarRegistroDinamico(['page_id'=>'home']), reinjetando o HTML sem perda de atributos.
-
-
Arquivos alterados:
recuperacao-dados-recursos.php(helperrdr_id_col+rdr_descompilar_registro+ log emrdr_processar),atualizacao-dados-recursos.php($idColno laço dinâmico, no cache$existDinamicoCachee emprocessarRegistroDinamico),tests/Unit/PHP/RecuperacaoDadosRecursosTest.php.
Pendências Runtime (com o operador)
-
Em um projeto real com tabela de ID customizada (ex.:
publisher_pagescom"id": "page_id"), rodar pull/deploy e confirmar geração dos arquivos físicos pela coluna lógica e round-trip sem perda de atributos. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-066 - Registro Dinâmico de Widgets do Sistema e Carregamento sob Demanda no Editor HTML (req-066)
-
[x] Banco de Dados:
-
[x] Migração Phinx para criação da tabela
widgetscom as colunas especificadas e índice único['id', 'language'](20260708100000_create_widgets_table.php, incluiproject).
-
-
[x] Configuração e Manifestos:
-
[x] Registro da tabela
widgetsemgestor/resources/tables_config.json(contratonatural_keypor[language, id]). -
[x] Inclusão do recurso
"widgets"nos arquivos JSON de manifesto para os módulos:menus,galleriesepublisher-index(pt-br + en;publisher-highlightsjá existente).
-
-
[x] Compilador de Recursos (
atualizacao-dados-recursos.php):-
[x] Alteração para coletar e empacotar o recurso
'widgets'dos módulos gerando o arquivoWidgetsData.json(pilha$widgets, chavename,versao=1). -
[x] Tratamento de órfãos para o recurso
'widgets'(índice$idxWidgetsporlang|id;db/orphans/WidgetsData.json).
-
-
[x] Roteamento Backend (
html-editor.php):-
[x] Nova rota AJAX
html-editor-widget-typespara carregar as categorias/tipos de widgets ativos. -
[x] Atualização da rota AJAX
html-editor-widgets-listpara aceitar o parâmetromodulee carregar os registros da tabela correspondente sob demanda, aplicando filtros decoluna_wheree sanitizando entradas (regex^[a-zA-Z0-9_]+$).
-
-
[x] Interface Frontend (
html-editor-visual-controls.js):-
[x] Remoção da lista estática
WIDGETS_MODULOS. -
[x] Carregamento inicial das categorias via AJAX utilizando
html-editor-widget-types. -
[x] Carregamento sob demanda (lazy loading) dos itens de cada categoria ao expandir o grupo, com cache local no JS (
widgetsCache[module]) para evitar redundâncias.
-
-
[x] Validação Estática:
-
[x] Executar
php -lnos arquivos alterados sem erros.
-
Evidência de Validação (BATCH-066)
Evidência automatizada reportada pelo executor em 2026-06-29 (ambiente: PHP 8.4.8, mbstring/pdo_sqlite/pdo_mysql):
-
php -l→ OK (3/3):gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php,gestor/bibliotecas/html-editor.php,gestor/db/migrations/20260708100000_create_widgets_table.php. -
node --check gestor/assets/interface/html-editor-visual-controls.js→ OK. -
JSON válido (
ConvertFrom-Json) → 5/5:tables_config.json,menus.json,galleries.json,publisher-index.json,publisher-highlights.json. -
Smoke read-only do compilador (inclui o arquivo com
SDD_NO_AUTORUNe chamacoletarRecursos()sem gravar): 8 widgets coletados (4 módulos × pt-br/en), todos comid/name/icon/tabelacorretos,versao=1,user_modified=0,coluna_where=NULL; 0 órfãos. -
composer test→ OK (67 tests, 255 assertions, 4 skipped gated por banco); a únicaPHPUnit Deprecationé pré-existente e alheia a este slice (sem testes novos — slice de UI + pipeline declarativo). -
Bump de cache-bust:
biblioteca-html-editor1.3.23→1.3.24(asset JS alterado). -
Arquivos alterados: migração nova;
tables_config.json;menus.json/galleries.json/publisher-index.json;atualizacao-dados-recursos.php;html-editor.php;html-editor-visual-controls.js.
Pendências Runtime (com o operador)
-
Rodar a esteira de atualização local (
?️ Projects - Update => Core, que aplica a migração Phinx + geraWidgetsData.json+ sincroniza) e confirmar a população correta da tabelawidgets(8 linhas). -
Validar no Editor HTML Visual que o carregamento das categorias ocorre dinamicamente (rota
html-editor-widget-types) e os itens são trazidos via AJAX (html-editor-widgets-listcommodule) apenas ao expandir cada categoria, com cache ao fechar/reabrir. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-067 - Correção de Exceção de CodeMirror Indefinido e Abas Travadas no Módulo de Formulários (req-067)
-
[x] Interface & Eventos (
html-editor-interface.js):-
[x] Envolver o registro do evento
"change"deCodeMirrorHtmlem um bloco de verificação de existência (typeof CodeMirrorHtml !== 'undefined' && CodeMirrorHtml). -
[x] Blindar as referências ao
CodeMirrorHtml,CodeMirrorCsseCodeMirrorCssCompiledno ouvinte do evento de backup ($('#gestor-listener').on(backupCallbackName, ...)). -
[x] Novo: Blindar as referências a
CodeMirrorHtmleCodeMirrorCssempreviewHtml(),totalDeSessoes(),getUpdatedHtmlWithValues()emenuDeSessoes()(early-return quando as instâncias não existem). -
[x] Novo: Causa-raiz identificada e corrigida — o editor estava aninhado em abas inativas no load (
forms-template/forms-preview), impedindo a instanciação do CodeMirror. Editor movido para seção raizConteúdo do Formulário/Form Contentfora das abas (6 HTMLs editar/adicionar/clonar × pt-br/en), espelhando opublisher-highlights.
-
-
[x] Widget público (
forms.widget.php):-
[x] Fallback ao template do banco (
templates,target='forms', viafields_schema.template_id) quando o campohtmldo registro está vazio, eliminando o widget renderizado vazio.
-
-
[x] Verificação Estática:
-
[x]
node --check gestor/assets/interface/html-editor-interface.js→ OK;php -l gestor/modulos/forms/forms.widget.php→ OK.
-
-
[x] Testes de Integração:
-
[x]
composer test→ 67/67 (255 assertions, 4 skipped) limpo.
-
Evidência de Validação (BATCH-067)
Rodada 1 (2026-06-29): guards no listener change e no handler de backup (#gestor-listener). node --check OK, php -l OK, composer test 67/67.
Rodada 2 — causa-raiz + widget (2026-06-29, escopo expandido pelo Engenheiro Chefe):
-
Causa-raiz: no
forms, o#html-editor#estava emdata-tab="forms-editor"(dentro dedata-tab="forms-template"), ambos inativos no load — diferente dopublisher-highlights, que renderiza o editor direto na página. Sem o editor visível/estável,CodeMirror.fromTextAreae as abas internas não se firmavam, deixandoCodeMirrorHtml/CodeMirrorCssindefinidos →previewHtml/totalDeSessoeslançavamundefined.getDoc()e travavam a troca de abas Fomantic. -
Correção estrutural: removida a sub-aba "Editor HTML" do
menuFormsTemplatee movido o#html-editor#para<h4 class="ui dividing header">Conteúdo do Formulário</h4>(en:Form Content) fora das abas, nos 6 HTMLs (editar/adicionar/clonar × pt-br/en).forms-viewnão renderiza editor (não afetado). -
Blindagem defensiva:
previewHtml(),getUpdatedHtmlWithValues(),totalDeSessoes(),menuDeSessoes()com early-return quando o CodeMirror não existe. -
Widget vazio (
forms.widget.php):forms_render()retornava''quandohtmldo banco estava vazio (template padrão não persistido por causa do mesmo bug do editor). Adicionado fallback que carregahtml/css/css_compiled/html_extra_headdo template (fields_schema.template_id). -
Cache-bust:
biblioteca-html-editor1.3.25→1.3.26. -
node --check(interface.js) OK;php -l(forms.widget.php) OK; grep confirmouConteúdo do Formulário/Form Content+#html-editor#nos 6 HTMLs e nenhumdata-tab="forms-editor"remanescente;composer test67/67 (255 assertions, 4 skipped). -
Arquivos: 6 HTMLs do
forms,html-editor-interface.js,forms.widget.php,html-editor.php(versão).
Pendências Runtime (com o operador)
-
Abrir a edição de um formulário (
forms/editar/), mudar de templates no dropdown e navegar pelas abas (incluindo o Editor HTML agora em "Conteúdo do Formulário"), confirmando ausência de erros no console e funcionamento da prévia. -
Renderizar um widget de formulário numa página publicada e confirmar que ele não vem mais vazio (incluindo forms que usam o template padrão, agora cobertos pelo fallback).
-
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-068 - Alinhamento Visual do CRUD e Painel de Conteúdo de Formulários com Menus (req-068)
-
[x] Modelos de CRUD (HTMLs):
-
[x] Remoção da aba "Template" (
forms-template) dos 6 HTMLs de adicionar, editar e clonar (pt-br + en). -
[x] Criação do cabeçalho de seção raiz "Conteúdo do Formulário" (en: "Form Content") fora e abaixo das abas principais.
-
[x] Inclusão do dropdown de seleção de modelo (
#template_id) e do novo menu de abasmenuConteudoFormcom as sub-abasforms-preview,forms-editoreforms-widget.
-
-
[x] Lógica de Interface (
forms.js):-
[x] Inicialização de abas da classe
.menuConteudoFormcom persistência emlocalStorageda sub-aba ativa (tabFormContentActive). -
[x] Redirecionamento da mudança de sub-aba do editor para
window.contentPageTabHandler()quando emforms-editor.
-
-
[x] Verificação Estática:
-
[x] Executar
node --checknos JS modificados ephp -lnos PHP correspondentes.
-
-
[x] Testes de Integração:
-
[x] Rodar
composer teste verificar aprovação completa.
-
Evidência de Validação (BATCH-068)
Evidência automatizada e visual reportada em 2026-06-29:
-
node --check gestor\modulos\forms\forms.js→ OK. -
php -l gestor\modulos\forms\forms.php→ OK. -
php -l gestor\modulos\forms\forms.widget.php→ OK. -
Reestruturação de abas Fomantic: resolvido o conflito entre o menu de abas principal (
menuForms) e o menu interno (menuConteudoForm) através da adição dos containers.forms-main-tabse.forms-content-tabsno HTML, configurados comocontextna inicialização do.tab()noforms.js. -
composer test→ OK (67 tests, 255 assertions, 4 skipped). -
Cache-bust:
biblioteca-html-editor1.3.25→1.3.26. -
Arquivos alterados: 6 HTMLs do forms,
forms.js,html-editor.php(versão).
Pendências Runtime (com o operador)
-
Abrir a página de edição de formulário e checar visualmente que a aba "Template" sumiu, a seção de conteúdo e abas secundárias se alinharam com Menus, e os botões e abas funcionam de forma responsiva sem erros.
-
Restrição respeitada: nenhum
git commit/git pushexecutado antes desta revisão.
BATCH-069 - Integração do Módulo de Formulários com o Controlador de Submissão de Biblioteca de Formulários (req-069)
-
[x] Biblioteca de Formulários (
formulario.php):-
[x] Adaptar
formulario_controlador()para processar múltiplos IDs de formulário (aceitando array ou string): normaliza$formIdem$formIdse processa DB/reCAPTCHA/acesso/params emforeach ($formIds as $fid)com reset por iteração. -
[x] Gerar as variáveis JavaScript estruturadas por ID (
$forms_js_vars[$fid]→gestor.form[fid]); para ID único (string) também injeta o formato plano via segundogestor_js_variavel_incluir('form', ...)(retrocompat legada). Bump de versãobiblioteca-formulario1.1.0→1.2.0(cache-bust doformulario.js).
-
-
[x] Script Controlador Frontend (
formulario.js):-
[x] Expandir o seletor inicializador para capturar tanto
.conn2flow-formquanto._forms-submissions-controller($('._forms-submissions-controller, .conn2flow-form')). -
[x] Ler a configuração individualizada de cada formulário de
gestor.form[formId]resolvendo o ID porform.attr('id') || form.attr('data-form-id')(com fallback ao objeto planogestor.form).showErrorpassou a isolar o erro na instância (form.prepend) em vez do seletor global.
-
-
[x] Integração do Widget (
forms.widget.php):-
[x] Chamar
gestor_incluir_biblioteca('formulario')+formulario_controlador(['formId' => $registro['id']])emforms_render(), removendo a inclusão deforms.widget.js(gestor_pagina_javascript_incluir(['tipo'=>'widget','modulo_id'=>'forms',...])).
-
-
[x] Saneamento de Arquivos:
-
[x] Deletar o arquivo redundante
forms.widget.js.
-
-
[x] Verificação Estática:
-
[x] Executar
node --checknoformulario.jsephp -lemformulario.php/forms.widget.php.
-
-
[x] Testes de Integração:
-
[x] Rodar
composer teste confirmar aprovação total.
-
Evidência de Validação (BATCH-069)
Evidência automatizada reportada pelo executor em 2026-06-29 (ambiente: PHP 8.4.8, PHPUnit 11.5.55):
-
php -l gestor/bibliotecas/formulario.php→No syntax errors detected. -
php -l gestor/modulos/forms/forms.widget.php→No syntax errors detected. -
node --check gestor/assets/interface/formulario.js→ OK. -
composer test→ OK (67 tests, 255 assertions, 4 skipped gated por banco); a únicaPHPUnit Deprecationé pré-existente e alheia a este slice (sem regressão vs. baseline BATCH-068; nenhum teste novo — slice de fluxo de widget/JS público sem hooks de banco testáveis isoladamente). -
Grep de sanidade:
_forms-submissions-controllernoformulario.jsrestou apenas no seletor inicial duplo;forms.widget.jsremovido e sem referências remanescentes (apenas orequire_oncedeforms.widget.php, que é o renderer). -
Decisão registrada: DEC-072.
-
Divergência de intake registrada: a prosa do req-069 §2 indicava
form.attr('id'), porém todos os templates (clássicocontact.htmle os 5 de widget) usamdata-form-ide nenhum defineidno<form>— o JS lêidcom fallbackdata-form-idpara casar com as chaves degestor.form.
Pendências Runtime (com o operador)
-
Adicionar mais de um widget de formulário na mesma página pública (ex.: contato no corpo + newsletter no rodapé) e verificar se as validações client-side e os envios via AJAX funcionam de forma independente para cada um, sem colisões em
gestor.form/localStoragenem exceções no console. -
Confirmar que o honeypot, o timestamp anti-replay e o reCAPTCHA (v2/v3) continuam presentes no fluxo do widget agora regido pela biblioteca.
-
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-070 - Parametrização de Scripts de Widget no Editor HTML e Dinamização do Mapeamento do Módulo Subscriptions
-
[x] Parametrização de Scripts de Widget no Editor HTML:
-
[x] Função
html_editor_componentenohtml-editor.phpaceita parâmetro'widget_js_include'(injetado emgestor.html_editor.widget_js_include). -
[x] Constante
WIDGET_SCRIPT_MODULESnohtml-editor-interface.jsrecupera valor degestor.html_editor.widget_js_include(fallback aos 4 módulos do core). -
[x]
montarWidgetAssetsHeadinjeta os scripts declarados emwidget_js_includemesmo sem assinatura[[widgets#...]]presente (preview do editor de forms =.conn2flow-formdireto); editores de página/layout/componente (chavenull) mantêm injeção por assinatura. -
[x] Chamadas para
html_editor_componenteemforms.php,menus.php,galleries.phpepublisher-index.phpatualizadas para passar o respectivo parâmetro.
-
-
[x] Recriação do Script de Widget de Formulário:
-
[x] Rota AJAX
'forms-render-editor-html'registrada no switch do backend emforms.phpapontando paraforms_ajax_render_editor_html(). -
[x] Função
forms_render_editor_htmlimplementada emforms.widget.php(reusa o builderformulario_montar_js_vars, extraído deformulario_controladoremformulario.php). -
[x] Arquivo
forms.widget.jsrecriado: chamada AJAX dedicada no preview, populawindow.gestor.form[formId]e carrega assíncronamenteinterface.jseformulario.js.
-
-
[x] Dinamização do Mapeamento no Módulo Subscriptions ([REDACTED]):
-
[x] Migração Phinx
20260710120000_add_signup_fields_to_subscriptions_plans.php(colunasis_signup,signup_field_email,signup_field_password,signup_field_password_confirm,signup_id_usuarios_perfis). -
[x] Variáveis de tradução adicionadas ao
subscriptions-plans.jsonempt-breen(6 chaves) + bump deversaodo módulo (1.0.0→1.1.0). -
[x] CRUD adicionar/editar persiste/carrega os 5 campos e resolve
#signup_profile_name#para o autocomplete. -
[x] Autocomplete AJAX habilitado para o alvo
perfis(endpointbuscar-perfis). -
[x] Novo endpoint AJAX
buscar-form-camposextrai campos ativos dofields_schemado formulário selecionado. -
[x]
subscriptions-plans.jse os 4 templates HTML (pt-br/en) com checkboxis_signup, container.sig-signup-fields-container, autocomplete de perfil e 3 selects de mapeamento (com toggle e pré-seleção). -
[x] Checkout dinâmico (
subscriptions.php,form_idpor slug+idioma) e signup dinâmico (subscriptions.ajax.public.php:is_signup/campos do plano;subscriptions_criar_usuariocomsignup_id_usuarios_perfis).
-
Evidência de Validação (BATCH-070)
Evidência automatizada reportada pelo executor em 2026-06-30 (ambiente: PHP 8.4.8):
-
conn2flow —
php -lOK:html-editor.php,formulario.php,forms.php,forms.widget.php,menus.php,galleries.php,publisher-index.php.node --checkOK:html-editor-interface.js,forms.widget.js,formulario.js.composer test→ OK (67 tests, 255 assertions, 4 skipped); a únicaPHPUnit Deprecationé pré-existente. O refator deformulario_controlador(extração do builderformulario_montar_js_vars) preservou o comportamento (suíte inalterada). Cache-bustbiblioteca-html-editor1.3.26→1.3.27. -
[REDACTED] —
php -lOK:subscriptions.php,subscriptions.ajax.public.php,subscriptions-plans.php, migração20260710120000.node --checkOK:subscriptions-plans.js. JSON válido:subscriptions-plans.json. Sem suíte de testes no projeto (composer test/phpunit.xmlausentes — conforme antecipado no req §3). Grep de sanidade: sem referências de código a$formToPlan/$planMapping/$schemaCheck(apenas comentários documentais).
Pendências Runtime (com o operador)
-
Rodar a migração Phinx no
[REDACTED](20260710120000) e o deploy (Update => Coredo projeto) para recompilarPaginasData.json/VariaveisData.json/checksums dos 4 templates e do módulo. -
Validar no Editor HTML de formulários que o preview do formulário inicializa interativamente (config via
forms-render-editor-html) e responde a submissões no iframe. -
No CRUD de planos: habilitar "Plano de Cadastro", vincular perfil via autocomplete e mapear os campos de e-mail/senha; salvar e conferir no banco.
-
Ativar
is_signup+ mapeamento nos planos que antes eram de cadastro (a migração nasce com default 0/null). -
Executar o checkout público de um plano de cadastro no
[REDACTED]e confirmar a criação da conta com o perfil dinamicamente atribuído. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-071 - Adição de Novos Tipos de Campos no Módulo de Formulários (req-071)
-
[x] Construtor de Formulários (Admin):
-
[x] Dropdown de tipos em
forms.jsatualizado para conterpassword,date,urlehidden. -
[x] Textarea de opções ativa para
hidden,text,textarea,numberedate(além deselect/radio/checkbox), via helpertypeUsesOptions. -
[x] Placeholders dinâmicos por tipo (
optionsPlaceholder): "Valor padrão do campo"/"Default field value" (hidden),min:3\nmax:100(text/textarea),min:18\nmax:100\nstep:1(number),min:2026-01-01\nmax:2026-12-31(date), listavalor:Rótulo(select/radio/checkbox).
-
-
[x] Renderizador de Widgets (Público):
-
[x]
forms.widget.phpsuporta os novos tipos no blocotype-input(oitem#typeresolve para o tipo nativo). -
[x] Valor padrão do
hiddenresolvido das opções (placeholder[[item#value]]+ injeção devaluequando ausente) e renderizado só como<input type="hidden">(sem label/wrapper). -
[x] Atributos de limite injetados a partir do campo Opções:
minlength/maxlength(text/textarea),min/max/step(number),min/max+ classeforms-date-picker(date). -
[x] Toggle de senha:
passwordenvolto em.forms-password-wrappercom botão.forms-password-toggle(íconeeye link icon), estilos inline compatíveis com Fomantic/Tailwind/Vanilla.
-
-
[x] Validações Centralizadas (Backend
formulario.php):-
[x] Limite de 254 caracteres estendido a
passwordeurl(nos dois blocos de max-length). -
[x] Validação de URL via
FILTER_VALIDATE_URL(quando preenchido). -
[x] Validações min/max via campo Opções: comprimento (text/textarea), valor numérico (number) e faixa de data (date); min-length agora genérico (
#min#).
-
-
[x] Frontend (
formulario.js):-
[x] Melhoria progressiva: date picker Fomantic (
.forms-date-picker) quando$.fn.calendarexiste; dropdown Fomantic emselect.ui.dropdownquando disponível; toggle de senha vanilla delegado. -
[x] Validações client-side de comprimento/valor/data/URL parseando
field.options(parseFieldLimits), com mensagens deprompts+ fallback.
-
-
[x] i18n: novas mensagens em
form-ui(pt-br/en): prompts (prompt-min-length/prompt-max-length/prompt-min-value/prompt-max-value/prompt-min-date/prompt-max-date/prompt-url) e ajax-messages (ajax-message-max-length/-invalid-url/-min-value/-max-value/-min-date/-max-date;-min-lengthgenérico).
Evidência de Validação (BATCH-071)
Evidência automatizada reportada pelo executor em 2026-06-30 (ambiente: PHP 8.4.8, PHPUnit 11.5.55):
-
node --check→ OK:gestor/modulos/forms/forms.js,gestor/assets/interface/formulario.js. -
php -l→ OK (3/3):gestor/modulos/forms/forms.widget.php,gestor/bibliotecas/formulario.php,tests/Unit/PHP/FormsWidgetFieldTypesTest.php. -
JSON válido:
gestor/modulos/forms/forms.json. -
Teste novo
tests/Unit/PHP/FormsWidgetFieldTypesTest.php→ OK (9 tests, 32 assertions): parse de limites, valor padrão do hidden (input-only), injeção minlength/maxlength (text/textarea), min/max/step (number), faixa + classe picker (date),type="url", wrapper/toggle de senha. -
composer test→ OK (76 tests, 287 assertions, 4 skipped gated por banco) (era 67; +9 deste lote); a únicaPHPUnit Deprecationé pré-existente e alheia ao slice. -
npm run test(vitest) → OK (2 files, 3 tests), sem regressão client-side. -
Cache-bust: módulo
forms1.0.0→1.1.0 (forms.js); bibliotecaformulario1.2.0→1.3.0 (formulario.js).
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Corepara recompilar o componenteform-ui(pt-br/en) com as novas mensagens e atualizar os checksums/versões. -
Criar formulário no admin contendo campos de cada um dos 4 novos tipos + limites (
text min:5/max:15,number min:18/max:120/step:1,date min:2026-06-01/max:2026-06-30,hiddencom valor padrão) e confirmar no preview os inputs nativos e o valor do hidden. -
Enviar o formulário no site público (Tailwind) e em ambiente Fomantic, validando toggle de senha, calendário/dropdown, e o barramento de URL inválida e dos limites tanto no front quanto no backend.
-
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-072 - Remoção do Campo e Metadado "hosting_plan" no Módulo de Planos de Assinatura
-
[x] Banco de Dados ([REDACTED]):
-
[x] Criada migração Phinx
20260710130000_remove_hosting_plan_from_subscriptions_plans.phppara dropar a colunahosting_planda tabelasubscriptions_planscom guardhasColumnedown()reversível.
-
-
[x] CRUD de Planos ([REDACTED]):
-
[x] Removido o campo
hosting_plando controladorsubscriptions-plans.phpem todos os fluxos de banco e placeholders. -
[x] Removido o input
hosting_plane seu respectivo HTML dos 4 templates de adicionar/editar planos (pt-br/en).
-
-
[x] Hidratação de Configurações ([REDACTED]):
-
[x]
subscriptions.hooks.phpatualizado para remover a coluna dobanco_selecte a atribuição a$planEntry['hosting_plan'].
-
Evidência de Validação (BATCH-072)
-
php -lOK:-
[REDACTED]/gestor/modulos/subscriptions-plans/subscriptions-plans.php -
[REDACTED]/gestor/modulos/subscriptions/subscriptions.hooks.php -
[REDACTED]/gestor/db/migrations/20260710130000_remove_hosting_plan_from_subscriptions_plans.php
-
-
Grep de sanidade OK nos arquivos runtime do escopo:
hosting_planpermanece apenas na nova migração de drop/reversão. -
composer db:migratetentado em[REDACTED], mas o checkout local não possuicomposer.json/vendor/bine o Composer retornou:There are no commands defined in the "db" namespace.
Pendências Runtime
-
Rodar a migração Phinx no ambiente
[REDACTED]configurado (o checkout local usado nesta execução não expõecomposer db:migrate). -
Validar no CRUD de planos que o campo não é mais exibido nem gera erros ao criar/editar registros.
-
Rodar a sincronização/deploy para garantir a atualização dos checksums/Data.json do módulo de planos.
BATCH-073 - Parametrização Dinâmica de E-mails e Integração de Estágios de Serviço em Planos
-
[x] Processamento de Checkout (
subscriptionsem[REDACTED]):-
[x] A função
subscriptions_ajax_forms_process()carrega o template de e-mail a partir de$schema['email']['message_component']com fallback aorder-confirmation-email. -
[x] A função utiliza o assunto do e-mail do campo
$schema['email']['subject']realizando a substituição de#name#,#code#,#formName#(com fallback a variáveis do módulo). -
[x] O status inicial e cor do e-mail de confirmação são baseados na flag
is_freedo plano cadastrado.
-
-
[x] Autocomplete de Componentes no forms (
conn2flow):-
[x] Rota AJAX
buscar-componentesadicionada emforms.php. -
[x] Inputs
#email_message_componentencapsulados em.sig-autocompletenos 6 templates HTML deforms(pt-br/en, adicionar/editar/clonar). -
[x] JS
forms.jsinicializa e delega os eventos de busca, seleção e limpeza do autocomplete.
-
-
[x] Layout do CRUD de Planos (
subscriptions-plansem[REDACTED]):-
[x] Os 4 templates HTML de planos reorganizados em segmentos lógicos (
Geral,Integração,Serviço,Pagamentos / Gateways,Mapeamento de Cadastro). -
[x] Restrições e sobras de layouts anteriores limpas dos arquivos do módulo.
-
-
[x] Estágios e Banco (
subscriptions-plansem[REDACTED]):-
[x] Migração de banco criada adicionando colunas
is_free(boolean) einitial_stage(varchar) emsubscriptions_plans. -
[x] Dropdown select
#select-initial_stage#adicionado na interface do CRUD e lógica do backend. -
[x] AJAX
buscar-estagiosimplementado no backend para filtrar estágios porstage_typee idioma. -
[x] JS
subscriptions-plans.jscarrega e repopula dinamicamente os estágios iniciais ao mudar o "Tipo de serviço".
-
Evidência de Validação (BATCH-073)
-
php -lOK:-
conn2flow/gestor/modulos/forms/forms.php -
[REDACTED]/gestor/modulos/subscriptions/subscriptions.ajax.public.php -
[REDACTED]/gestor/modulos/subscriptions/subscriptions.php -
[REDACTED]/gestor/modulos/subscriptions/subscriptions.hooks.php -
[REDACTED]/gestor/modulos/subscriptions-plans/subscriptions-plans.php -
[REDACTED]/gestor/db/migrations/20260710140000_add_free_and_initial_stage_to_subscriptions_plans.php
-
-
node --checkOK:-
conn2flow/gestor/modulos/forms/forms.js -
[REDACTED]/gestor/modulos/subscriptions-plans/subscriptions-plans.js
-
-
JSON válido:
[REDACTED]/gestor/modulos/subscriptions-plans/subscriptions-plans.json,conn2flow/gestor/modulos/forms/forms.json. -
Grep de sanidade: sem sobras de
isCustomPlan,isCloudNano,emailSubjectId,custom-order-confirmation-email,email-subject-custom-confirmationouform-pro-cloud-nanoemsubscriptions.ajax.public.php. -
composer testemconn2flow: OK, 76 testes, 287 assertions, 4 skipped, 1 PHPUnit deprecation. -
composer db:migratetentado em[REDACTED], mas o checkout local retornou:There are no commands defined in the "db" namespace.
Pendências Runtime
-
Rodar a migração Phinx no ambiente
[REDACTED]configurado (este checkout local não expõecomposer db:migrate). -
Validar o autocomplete de componentes de e-mail no construtor de formulários.
-
Validar o agrupamento visual de segmentos no CRUD de planos e a carga dinâmica de estágios por tipo de serviço.
BATCH-074 - Dinamização Completa de Planos e Saneamento de Hardcodes no Subscriptions
-
[x] Saneamento de Dicionários Estáticos de Tradução de Nomes de Planos (§1):
-
[x] Helper
subscriptions_obter_nome_plano($planSlug, $lang)emsubscriptions.hooks.phpconsultasubscriptions_plans.nameporid+language(status≠'D'), com fallback humanizado do slug. -
[x] Substituídos os 5 dicionários estáticos (
$paypalPlanNames×2 nos hooks;$paypalPlanNames/$planDisplayNames/$planNames×3 no controlador) pelo helper.
-
-
[x] Dinamização de Filtros por Prefixo de Formulário (
form-pro-%) (§2):-
[x] Helper
subscriptions_obter_form_ids_planos()(form_ids distintos de planos ativos) +subscriptions_obter_form_ids_clausula()(geraform_id IN (...)escapado, fallbackLIKE 'form-pro-%'quando vazio). -
[x] Atualizados os 3 filtros (
subscriptions.hooks.php×2 do IPN/retorno +subscriptions.php×1) para usar a cláusula dinâmica.
-
-
[x] Dinamização do Template de Checkout (
subscription-checkout.html) (§3):-
[x] Unificados os 6 blocos por plano em uma única estrutura com placeholders (
#plan_name#,#plan_description#,#plan_price_card#,#checkout_form#) — ~990→~135 linhas (pt-br/en). -
[x] Divergência aprovada (orientação do usuário humano): em vez de blocos fixos
plan_fields_signup/plan_fields_custom, o formulário do plano é renderizado dinamicamente viaforms_render(['form_id'=>...])(lêforms.htmlporform_id), preservando os campos específicos de cada plano. Ver DEC-077.
-
-
[x] Simplificação e Saneamento do Template da Landing Page (
subscription.html) (§4):-
[x] Removido o marketing estático legado (Hero, Filosofia, VPS, “Por que pagar”, FAQ) — ~690→~55 linhas.
-
[x] Mantidos apenas header + grid dinâmico (
custom_layout/plans_grid/plan_card+ placeholders) + rodapé minimalista (pt-br/en).
-
-
[x] Saneamento do Template de Callback (
subscription-start.html) (§5):-
[x] Neutralizados os textos das seções de status (jargão hospedagem/cloud/projeto/“our subscription platform” → linguagem de assinatura), sem alterar marcadores nem placeholders.
-
[x] Preservadas as variáveis dinâmicas (
#plan_display_name#/#plan_name#/#customer_name#/#txn_id#).
-
-
[x] Proteção de Campos Password em Submissões (
formulario.php, conn2flow) (§6):-
[x] Valor de campos
type==='password'gravado como''emforms_submissions.fields_values(chave preservada); valor em texto plano mantido em$_POSTpara o signup. -
[x] Defesa em profundidade: campo
passwordomitido também no laço do e-mail de notificação/confirmação.
-
-
[x] Dinamização do Loop de Células de Plano na Página de Checkout (§7):
-
[x] Removidos
$plans/$planCelMap; resolução dinâmica emsubscriptions_planspor slug + aliases legados (aceleracao/mentoria/personalizado); gate de pagamento portotal_payments > 0.
-
Evidência de Validação (BATCH-074)
Evidência automatizada reportada pelo executor em 2026-06-30 (ambiente: PHP 8.4.8):
-
php -l→ OK (3/3):subscriptions.php,subscriptions.hooks.php([REDACTED]),gestor/bibliotecas/formulario.php(conn2flow). -
Integridade de marcadores HTML balanceada (1 abre + 1 fecha cada): checkout (
valid_plan/invalid_plan/step_form/step_payment/step_success) e landing (custom_layout/plans_grid/plan_card) nos dois idiomas; placeholders presentes (#plan_name#/#plan_description#/#plan_price_card#/#checkout_form#/#paypal_primary_*#no checkout;#plan_*#na landing). -
Grep de sanidade: sem
$paypalPlanNames/$planDisplayNames/$planNames/form-pro-%(exceto o fallback intencional na cláusula) e sem$activePlanCel/$planCelMap(exceto comentário) no módulo. -
composer test(conn2flow) → OK (76 tests, 287 assertions, 4 skipped gated por banco); sem regressão da §6 (a únicaPHPUnit Deprecationé pré-existente). Sem suíte no[REDACTED](phpunit.xml/composer testausentes, conforme batches anteriores).
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Coreno[REDACTED]para recompilarPaginasData.json+ checksums dos templates alterados (checkout/landing/callback) e sincronizar. -
Confirmar que os formulários referenciados pelos planos têm
htmlsalvo na tabelaforms(o checkout renderiza viaforms_render; semhtmlo bloco do formulário sai vazio). -
Executar o checkout público de um plano pago, um gratuito (
is_free) e um sob medida (total_payments=0): formulário renderizado, card de preço correto, fluxo form→payment/success sem avisos de PHP. -
Simular um retorno/IPN de webhook e confirmar que a submissão é localizada pela cláusula dinâmica
form_id IN (...). -
Confirmar no banco que submissões com campo
passwordgravamvaluevazio emfields_valuese que o signup continua criando a conta (senha lida de$_POST). -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-075 - Dashboard Site Toolbar, Agendamento de Páginas e Extensões do Editor HTML (req-075)
Lote consolidado (6 metas) implementado em slices sequenciais. Plano em BATCH-075.md.
Slice 1 — Meta 1: Botão "Acessar Site" no Layout Administrativo
-
[x] Âncora
#menu-site-btnadicionada ao grupoui icon buttonsda.menu-controls(primeiro item; ordem Acessar site → Dashboard 3D → Fechar), nos layouts adminpt-breen. -
[x]
href="@[[pagina#url-raiz]]@"(raiz pública), íconeexternal alternate, tooltip localizado ("Acessar site" / "Visit site"),data-position="bottom left"alinhado aos botões irmãos. -
[x] Notação
@[[...]]@literal preservada (cópia do banco — não remover arrobas).
Evidência de Validação (Slice 1)
Evidência automatizada reportada em 2026-07-09:
-
Balanceamento de tags:
<a>/</a>= 2/2 em cada layout (pt-br e en) após inserção do elemento completo — sem desbalanceamento. -
Grep confirma
menu-site-btnpresente nos dois arquivos com ohref="@[[pagina#url-raiz]]@"e os tooltips corretos por idioma. -
Arquivos alterados:
gestor/resources/pt-br/layouts/layout-administrativo-do-gestor/layout-administrativo-do-gestor.html,gestor/resources/en/layouts/layout-administrativo-do-gestor/layout-administrativo-do-gestor.html.
Notas de escopo (Slice 1)
-
Posicionamento: o intake diz "ao lado direito dos botões
#menu-dashboard3d-btne#menu-close-btn". Interpretação aplicada: inserido como primeiro item do mesmo grupoui icon buttons(Acessar site → Dashboard 3D → Fechar), mantendo o "X" (Fechar) como último por UX. Ajuste trivial caso a chefia prefira posição diferente. -
Alvo do link: sem
target(navega na mesma aba), espelhando o link de dashboard já existente no layout (linha 60). Fácil trocar paratarget="_blank"se preferir manter o admin aberto.
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Corepara recompilarPaginasData.json/layouts e sincronizar (o layout é recurso de banco). -
Validar no navegador que o botão aparece na barra de controles do menu admin e redireciona para a raiz pública do site.
Slice 3a — Meta 2: Dashboard Site Toolbar (iframe + rota + injeção)
Reordenada à frente das Metas 5/6 porque o operador já havia scaffoldado a estrutura (rota, switch, funções vazias, refactor de gestor_acesso). Construído sobre esses esqueletos.
-
[x] Página iframe
dashboard-site-toolbar(pt-br/en) preenchida com Tailwind: barra de altura total (~30px via iframe), acesso ao painel,<!-- menu -->, botões "Editar Página" (#c2f-toolbar-edit, live edit — Meta 3, comportamento pendente) e "Editar no Painel" (#c2f-toolbar-edit-advanced,target="_parent"). Rotadashboard-site-toolbar/já registrada nodashboard.json(layoutlayout-pagina-simples,framework_css: tailwindcss). -
[x]
dashboard_site_toolbar()(dashboard.php): lêpage_id/publisher_idda query string (contexto da página hospedeira) e monta a URL de edição avançada — a página é carregada porid(=paginas.id) em ambos os módulos, mas o publicador precisa TAMBÉM dopublisher_id(distinto do id da página) p/ fixar o contexto:publisher-pages/editar/?id=<paginas.id>&publisher_id=<paginas.publisher_id>quando publicador, senãoadmin-paginas/editar/?id=<paginas.id>. -
[x]
dashboard_site_toolbar_menu()(dashboard.php): dropdown Tailwind (basemenus-dropdown) com os módulos que o perfil pode acessar (link para a página raiz do módulo,target="_parent"), label i18n (Módulos/Modules). -
[x]
gestor_dashboard_toolbar()(gestor.php): injeção do iframe fixo (top, 100% largura, 30px,z-indexmáximo) logo após<body>+ inclusão dodashboard.toolbar.js(offsetmargin-top:30pxna hospedeira) viagestor_pagina_javascript_incluir(tipo=toolbar, modulo_id=dashboard). Gating: só parausuario-id > 0egestor_acesso('editar','admin-paginas')e página pública (exclui layoutlayout-administrativo-do-gestorepaginaIframe). Resolveid/publisher_idda hospedeira consultandopaginasporcaminho+language. Chamada no bloco de finalização degestor.phpantes degestor_pagina_extra_head_e_javascript()(apósgestor_pagina_widgets()) p/ o JS auxiliar ser incluído, passandocaminho.
Evidência de Validação (Slice 3a)
Evidência automatizada reportada em 2026-07-09 (PHP 8.4.8):
-
php -l gestor/gestor.php→ OK;php -l gestor/modulos/dashboard/dashboard.php→ OK. -
node --check gestor/modulos/dashboard/dashboard.toolbar.js→ OK. -
dashboard.json→ JSON VALID. -
composer test→ 76/76 (287 assertions, 4 skipped, 1 deprecation pré-existente) — sem regressão após a injeção no coregestor.php.
Notas de escopo / decisões (Slice 3a)
-
Gating do render compartilhado: a finalização em
gestor.php(~L2180,echo $_GESTOR['pagina']) é usada por páginas públicas e admin (ointerface_finalizar()não dáexit, retorna). Por isso o gating é explícito (exclui layout admin + iframe). Para anônimos,gestor_dashboard_toolbar()retorna antes de qualquer query (checagem deusuario-id), sem custo. -
dashboard.toolbar.jsviagestor_pagina_javascript_incluir(correção do Chefe): o JS é incluído pela função padrão (tipo=toolbar,modulo_id=dashboard→ URLdashboard/toolbar.js, mapeada ao físicodashboard.toolbar.jsporarquivo-estatico.php;tiposem ponto p/ casar/^[A-Za-z0-9-]+$/). Como ela empilha emjavascript-fim(despejado porgestor_pagina_extra_head_e_javascript()), a chamada da toolbar roda ANTES dessa etapa. -
URL de edição avançada (Meta 4) (correção do Chefe): a página carrega por
id(=paginas.id), mas o id da página e opublisher_id(id da publicação vinculada) são distintos — então o publicador recebe os dois:publisher-pages/editar/?id=<paginas.id>&publisher_id=<paginas.publisher_id>(opublisher_idfixa o contexto viapublisher_pages_publisher()); comum:admin-paginas/editar/?id=<paginas.id>. -
Pendente nesta Meta: comportamento do botão "Editar Página" (edição live in-place) é a Meta 3 (slice próprio); a detecção/URL de publicador pode ser refinada na Meta 4.
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Core(recompilaPaginasData.jsonda nova páginadashboard-site-toolbar+ removetestes-do-dashboard, aplica migração se houver) e sincronizar. -
Logar como usuário com permissão de editar páginas, abrir uma página pública do site e confirmar: a barra de ~30px aparece no topo, o conteúdo é empurrado 30px, o dropdown de módulos lista os módulos acessíveis, e "Editar no Painel" abre
admin-paginas/publisher-pagesconforme a origem da página. -
Confirmar que anônimos e páginas do painel administrativo não recebem a toolbar.
Slice 3b — Meta 3: Edição visual live via toolbar (Approach B / Path Y — fundação)
Estratégia aprovada pelo Chefe: Path Y — o editor carrega o HTML ORIGINAL da tabela (com @[[var]]@ e comentários de widget preservados; o html-editor já os trata como placeholders opacos), e o preview é que deve ganhar fidelidade visual à página live. Não se edita o DOM renderizado (isso queimaria vars/widgets). Sem motor de reconciliação.
-
[x] UX (aval do Chefe): editar NÃO abre overlay que substitui a página — revela controles ABAIXO da toolbar. Botão "Editar Página" (
#c2f-toolbar-edit) faz toggle de uma segunda linha#c2f-toolbar-editbar(44px, oculta) dentro do próprio iframe, e postac2f-toolbar:resize/edit-start/edit-cancel/edit-save(pt-br/en). -
[x] Toolbar dinâmica: o iframe base 30px é redimensionado pelo [REDACTED] receber
c2f-toolbar:resize {height}— mesma estratégia do seletor de linguagens (global.js). A toolbar mede dropdown de módulos (hover) + editbar aberta viacomputeHeight(). Transparência (html,body{background:transparent}+ iframebackground:transparent/allowtransparency) faz a área expandida mostrar a página atrás; só barra/dropdown/editbar ficam opacos. -
[x] Refinamentos visuais: marca usa
@[[pagina#url-raiz]]@images/LogomarcaIcone.png+ texto "Dashboard"; menu (PHP) recebeuid="c2f-toolbar-menu"; z-index da toolbar 2147483000. -
[x] Motor marker-based (estratégia FINAL) — decisão registrada: editor mostra a página RENDERIZADA;
@[[var]]@/widgets viram caixas de destaque protegidas guardando o marcador; save reconstrói determinístico (caixa→marcador, resto→editado). -
[x] Backend — endpoint de save:
dashboard_ajax_site_toolbar_save()(ajax-opcaosite-toolbar-save) gravahtml/css/css_compiled/html_extra_headempaginasporid+language, permissãogestor_acesso('editar','admin-paginas'),banco_update_campoescapando.php -lOK,composer test76/76. (Teste unitário gated por banco — não adicionado, seguindo precedente de endpoints acoplados a banco/POST.) -
[x] Motor completo (marker-based):
-
Backend
site-toolbar-render(dashboard_ajax_site_toolbar_render): lêpaginas.htmloriginal, envolve widgets (wrapper por comentário + inline@[[widgets#...]]@) e variáveis@[[var]]@(em texto) em caixas de destaque.c2f-dyn-box(data-c2f-marker= base64 do marcador); vars em atributo resolvem para valor. Helpersdashboard_site_toolbar_box/_render_widget/_boxes_widgets/_resolver_var/_boxes_variaveis. -
Wrapper
#c2f-page-contentno conteúdo da página (emgestor_pagina_layout, gated porgestor_dashboard_toolbar_ativo()— mesmo gate da injeção). -
Editor visual REAL (correção do Chefe — não
contentEditable):html-editor.jsadaptado para aceitarcontentRoot(defaultdocument.body→ clássico intacto); escoparesolveEditable/getUserContentNodes/TreeWalkers/inserção ao root; auto-init guardado porwindow.__c2fHtmlEditorNoAutoInit; expõewindow.HtmlEditorClass.dashboard.toolbar.js(edit-start): fetch render → troca#c2f-page-content→ carrega jQuery (se ausente) +interface/html-editor.js(noAutoInit) →new HtmlEditorClass({contentRoot:#c2f-page-content})→ editor real ativo (caixas tracejadas de seleção, floating toolbar, styler, DnD). Save:getCleanHtml()→DOMParser→reconstructOriginal(caixas→marcadores) → POST → reload. Cancel = reload. -
Modal fallback vanilla (autorizado):
ensureFallbackModal()injeta#html-editor-modalvanilla (inline styles portáveis) com#text-field/#image-field/#code-field+textareas quando ausente;showModal/hideModalvanilla quando não há Fomantic (usaFomanticModal); botões Salvar/Cancelar/backdrop ligados; code-edit usa#element-codesem CodeMirror. Bumpbiblioteca-html-editor1.3.28→1.3.29. Dependência dura: só jQuery (carregado on-demand); Fomantic/CodeMirror opcionais (degradam graciosamente).
-
Evidência de Validação (Slice 3b — fundação)
Evidência automatizada em 2026-07-09 (PHP 8.4.8):
-
node --check gestor/modulos/dashboard/dashboard.toolbar.js→ OK. -
php -l gestor/gestor.php→ OK;php -l gestor/modulos/dashboard/dashboard.php→ OK. -
composer test→ 76/76 (287 assertions, 4 skipped) — sem regressão.
Pendências (refino + runtime)
-
Refino (próximo): fidelidade visual do preview do editor à página live (
html-editor-interface.jseditorHtmlVisualConteudo/srcdoc) — incluir head/CSS/framework/layout da página para eliminar a leve diferença de CSS. -
Runtime (operador): após
Update => Core, logar como editor, abrir página pública, clicar "Editar Página" → a barra de edição abre abaixo da toolbar e a página fica editável (caixas de var/widget protegidas); "Salvar alterações" persiste e recarrega; confirmar que@[[var]]@e widgets seguem preservados nopaginas.htmlapós salvar.
Slice 2 — Meta 5: Agendamento de Páginas e Datas Retroativas
-
[x] Migração
20260712100000_add_publish_window_to_paginas.php(colunasdata_publicacao_inicio/data_publicacao_fimdatetime null, guardshasColumn,down()reversível).paginasjá tinhadata_criacao/data_modificacao. -
[x] Helpers globais
gestor_parse_datetime_br()(dd/mm/yyyy HH:mm ou ISO → DATETIME; null se vazio/inválido) egestor_datetime_para_input(). -
[x] Roteamento 404 (
gestor.php): a query de página ativa (principal + fallback de idioma) filtra(data_publicacao_inicio IS NULL OR <= NOW())e(data_publicacao_fim IS NULL OR >= NOW())→ fora da janela = 0 linhas = 404. Páginas de sistema (janela NULL) sempre passam. -
[x] Controladores
admin-paginasepublisher-pages(adicionar/clonar): camposdata_publicacao_inicio/fim(se informados) +data_criacao/data_modificacaoretroativas (valor informado ou NOW()). Editar (diff): idem, com preserve-on-empty (só altera janela quando data válida;*_limparpara NULL) edata_modificacaorespeitando override. -
[x] 12 forms (admin-paginas + publisher-pages × adicionar/editar/clonar × pt-br/en) com a seção "Agendamento e datas" (
<!-- agendamento-datas -->, 4<input type="datetime-local">) inserida após<!-- permissao-pagina > --></div>.
Evidência de Validação (Slice 2)
-
php -lOK:gestor.php,admin-paginas.php,publisher-pages.php, migração.composer test76/76. Seção inserida nos 12 forms (perl bytes-crus preservou acentoscriação/modificação).
Limitações / Pendências (Slice 2)
-
Editar não pré-preenche os valores atuais das datas (campos vazios; preserve-on-empty evita apagar). Alteração só de agendamento (sem outro campo mudar) pode não disparar o save no editar (bloco dentro do finalize de update). Formato friendly dd/mm/yyyy é aceito pelo parser mas os inputs usam
datetime-local(ISO). Runtime: migração viaUpdate => Core; testar página agendada/expirada → 404; datas retroativas gravadas.
Slice 4 — Meta 6: Atalho de Edição Administrativa de Widget no Editor HTML
-
[x] Botão
he-tb-widget-admin(íconeexternal alternate) no#html-editor-floating-toolbar(html-editor.js), visível só quando um.conn2flow-widget-wrapperestá selecionado (updateWidgetAdminButtonemupdateSelectionUI). -
[x]
openWidgetAdmin(): abre<raiz><data-widget-type>/editar/?id=<data-widget-slug>em nova aba (raiz viawindow.parent.gestor.raizcom fallback). Cache-bustbiblioteca-html-editor1.3.27→1.3.28.
Evidência de Validação (Slice 4)
-
node --check gestor/assets/interface/html-editor.js→ OK.composer test76/76. Runtime: selecionar um widget no editor e confirmar que o botão abre o módulo (ex.:menus/editar/?id=<slug>).
Slice 5 — Rodada de Correções (pontos 1-5 + edição de layout + user_modified)
Feedback do Chefe após teste da fundação. Consolidado em slice único conforme a instrução "faça tudo sem parar até terminar".
-
[x] Ponto 1 — controles no
#c2f-toolbar-editbar(sempre visível durante a edição): botõesscreenPagina(desktop 100% / tablet 768px / mobile 375px),html-editor-undo-btn,html-editor-redo-btnehtml-editor-add-btn. O undo/redo/add postamc2f-toolbar:edit-undo/edit-redo/edit-addao host, que acionac2fEditor.undo()/redo()e abre o painel "+" (openAddPanel).screenPaginapostac2f-toolbar:edit-screen {width}→setEditScreenredimensiona o#c2f-layout-root/#c2f-page-contentna hospedeira. -
[x] Ponto 1b — painel de inserção de widgets no add-btn: o
html-editor-add-btnabre painel host (openAddPanel) que lista elementos básicos e grupos de widgets (reuso dehtml_editor_ajax_widget_types/html_editor_ajax_widgets_listvia endpointssite-toolbar-widget-types/site-toolbar-widgets-listnodashboard.php, que incluemgestor_incluir_biblioteca('html-editor')). Inserção viac2f-toolbar:edit-insert(elemento) e inserção direta de widget no editor. -
[x] Ponto 2 — imagepick:
requestBackgroundImage()nohtml-editor.jscai emwindow.promptde URL quando não há confightml_editor.imagepick(contexto da toolbar não tem o módulo admin-paginas). O botãohe-bgimage-pickvolta a responder. -
[x] Ponto 3 — datas via
formato.php(helpers removidos dogestor.php):formato_data_hora_br_para_datetime()aceita BR (DD/MM/AAAA [HH:MM]) e ISO (AAAA-MM-DD[THH:MM], odatetime-localfoi mantido), eformato_data_hora_datetime_para_input()faz o inverso (DATETIME→Y-m-d\TH:i).admin-paginas.php/publisher-pages.phppassam a incluirformatoe usar essas fns. -
[x] CodeMirror in-place:
dashboard.toolbar.js(ensureCodeMirror/initCodeMirrorField) inicializa o CodeMirror sobre o#element-codedo modal do editor live (carrega CSS/JS on-demand), espelhando oadmin-paginas. -
[x] Ponto 4 — edição do LAYOUT (via
layout_id, só o body-inner):dashboard_ajax_site_toolbar_renderretorna tambémlayout_id/layout_html(body-inner do registrolayoutsdo banco, renderizado com caixas e$preservar_atributos=truepara manter@[[pagina#url-raiz]]@etc. literais);#c2f-layout-root(data-layout-id) envolve o body-inner na hospedeira.saveEditdivide: conteúdo (#c2f-page-content)→paginas; layout (#c2f-layout-rootcom o#c2f-page-contentrecolocado como__C2F_CORPO__→@[[pagina#corpo]]@)→layoutsviadashboard_site_toolbar_salvar_layout(safeguard exige@[[pagina#corpo]]@no body-inner salvo). -
[x] Ponto 5-save — histórico + backup:
dashboard_ajax_site_toolbar_savegrava, além do campo,interface_backup_campo_incluir+interface_historico_incluirno módulo-dono (publisher-pagessepublisher_id, senãoadmin-paginas), espelhando oadmin-paginas. -
[x] Ponto 5-dropdown — restauração de backups no editbar: botão
#c2f-backups-btnpostac2f-toolbar:edit-backups; hostopenBackupPanelbuscasite-toolbar-backups(listaid/versao/datadebackup_camposdoid_paginas+módulo-dono+campo='html'), e ao clicar buscasite-toolbar-backup-get(valor renderizado com caixas) e injeta em#c2f-page-content. -
[x] user_modified=1: o save marca
user_modified=1(+versao+1 +data_modificacao=NOW()) tanto empaginasquanto emlayouts(quando o layout é alterado no mesmo salvamento).
Evidência de Validação (Slice 5)
Evidência automatizada em 2026-07-09 (PHP 8.4.8):
-
node --check gestor/modulos/dashboard/dashboard.toolbar.js→ OK. -
php -lOK:gestor/modulos/dashboard/dashboard.php,gestor/gestor.php,gestor/bibliotecas/formato.php. -
composer test→ 76/76 (287 assertions, 4 skipped, 1 deprecation pré-existente) — sem regressão. -
Cache-bust
biblioteca-html-editoraté1.3.30. -
Arquivos alterados:
dashboard.php,dashboard.toolbar.js,dashboard-site-toolbar.html(pt-br/en),html-editor.js,html-editor.php(versão),formato.php,gestor.php,admin-paginas.php,publisher-pages.php.
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Core(aplica migração de janela de publicação + recompilaPaginasData.json/layouts) e sincronizar. -
Logar como editor, abrir página pública, "Editar Página": confirmar controles no editbar (telas responsivas, undo/redo, add com widgets, backups), imagepick por URL, edição de conteúdo e de layout (body-inner), salvamento com histórico/backup e
user_modified=1empaginas/layouts, e restauração de um backup pelo dropdown.
BATCH-076 - Opção de Exclusão de contents/ em Tarefas de Deploy e Sincronização (req-076)
-
[x] Configuração de Tarefas (
.vscode/tasks.json):-
[x] Adicionar o input seletor
contentsChoice(Sim/Não) com valor padrão "Sim". -
[x] Atualizar as tarefas
"?️ Projects - Deploy Current Project","?️ Projects - Deploy Project -> ID"e"?️ Projects - Synchronize => Files -> ID"para aceitar e propagar o parâmetro--contents ${input:contentsChoice}.
-
-
[x] Script de Deploy (
deploy-project-v2.sh):-
[x] Aceitar o parâmetro
--contentse tratar o valor "Não" para excluir a pastacontents/da compressão 7z. -
[x] Quando
gitDeployestiver ativo e a opção for "Não", filtrar a lista de arquivos alterados para excluir qualquer alteração vinda decontents/.
-
-
[x] Script de Sincronização (
synchronize-project.sh):-
[x] Aceitar o parâmetro
--contentse tratar o valor "Não" para adicionar--exclude "contents/"no comandorsync.
-
-
[x] Validação:
-
[x] Sintaxe JSON e bash (
bash -n) corretas. -
[x] Confirmar que a exclusão da pasta de uploads de fato ocorre no ZIP e no Rsync em testes manuais rápidos.
-
Evidência de Validação (BATCH-076)
Evidência automatizada e estática reportada pelo executor em 2026-07-09:
-
Sintaxe de
.vscode/tasks.jsonvalidada com sucesso. -
Sintaxe bash de
deploy-project-v2.shesynchronize-project.shvalidada viabash -ne opções de--helptestadas com sucesso. -
git diff --checkexecutado sem erros nos arquivos modificados.
BATCH-077 - Desacoplamento de Scripts do Iframe e Mapeamento Inteligente de Variáveis no Live Editor (req-077)
Slice 1 — Desacoplamento do script da toolbar
-
[x] Lógica JS da toolbar extraída do
<script>inline para o arquivo estáticogestor/modulos/dashboard/dashboard.iframe-toolbar.js. -
[x] Tag
<script>…</script>removida dos 2 templatesdashboard-site-toolbar.html(pt-br/en). -
[x] Injeção via
gestor_pagina_javascript_incluir(Array('tipo'=>'iframe-toolbar','modulo_id'=>'dashboard'))emdashboard_site_toolbar()(URLdashboard/iframe-toolbar.js→ físicodashboard.iframe-toolbar.js, casando a regex/^[A-Za-z0-9-]+$/doarquivo-estatico.php). -
[x] Órfão vazio
dashboard.iframe.toolbar.js(0 bytes, sem referências) removido.
Slice 2 — Mapeamento inteligente de variáveis/atributos
-
[x] Backend
dashboard_ajax_site_toolbar_renderdevolve o HTML CRU original (content_raw=paginas.html;layout_raw= body-inner do layout com o slot@[[pagina#corpo]]@preenchido por#c2f-raw-content). Campos legados (html/layout_html) preservados p/ retrocompat. -
[x]
startEdit(dashboard.toolbar.js) não substitui maisroot.innerHTML; guarda o cru em#paginaHTMLAntesEdicao(display:none) e chamamapTree(root, backup)preservando o DOM vivo. -
[x] Variável em atributo → tag viva marcada com
data-c2f-variable="ID_VAR_N"+varMap[ID]={param,variable,valor}(valor resolvido segue visível no editor). -
[x] Variável em texto →
annotateTextVarsenvolve o trecho numspan.c2f-var-boxprotegido (contenteditable=false). -
[x] Widget →
mapTreeenvolve a expansão viva numdiv.c2f-widget-boxatômico via âncora estrutural. -
[x]
saveEdit/reconstructOriginalrestauradata-c2f-variable→@[[…]]@(só quando o valor não foi alterado), caixas→marcador original, e separa#c2f-page-content→paginasdo resto do layout (#c2f-page-content→@[[pagina#corpo]]@)→layouts.
Evidência de Validação (BATCH-077)
Evidência automatizada reportada pelo executor em 2026-07-10:
-
node --check→ OK (2/2):dashboard.iframe-toolbar.js,dashboard.toolbar.js. -
php -l gestor/modulos/dashboard/dashboard.php→No syntax errors detected. -
Balanceamento de tags nos 2 HTMLs:
<div>5/5,<script>0 (script removido). -
Teste de lógica do motor (harness
happy-domcarregando odashboard.toolbar.jsREAL e exercitando o fluxo via message-busedit-start/edit-savecomfetchmockado): 16/16 checks OK, cobrindo:-
Atributos (caso de aceite — página raiz do sistema):
<a>/<img>com@[[pagina#url-raiz]]@recebemdata-c2f-variable; valor resolvido preservado no editor; no save os@[[pagina#url-raiz]]@são reconstruídos emhref/src,data-c2f-variableremovido e<h1>intacto. -
Variável de texto:
@[[usuario#nome]]@vira caixa protegida com o valor resolvido; save reconstrói o marcador no texto. -
Widget: bloco de widget vira
.c2f-widget-boxatômica contendo o render vivo;<footer>fora da caixa preservado; save reconstrói o marcador<!-- widgets#… -->(com o mockup) e não grava o HTML renderizado.
-
-
Decisão registrada: DEC-079.
-
Arquivos: novo
dashboard.iframe-toolbar.js;dashboard.toolbar.js;dashboard.php;dashboard-site-toolbar.html(pt-br/en); removidodashboard.iframe.toolbar.js.
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Coree sincronizar (as páginasdashboard-site-toolbarsão recurso de banco — a remoção do<script>do template e o novo JS estático só refletem após o deploy). -
Logar como editor, abrir uma página pública com
@[[pagina#url-raiz]]@(ex.: raiz do sistema), "Editar Página" e confirmar: (1) o iframe da toolbar inicializa sem erros no console (script agora estático); (2) o layout/scripts/CSS do site vivo continuam funcionando durante a edição (sem quebra); (3) após editar e salvar, as imagens/links com@[[pagina#url-raiz]]@permanecem preservados no banco (não queimados) — inspecionarpaginas.html/layouts.html. -
Confirmar o comportamento do editor visual real (
html-editor.js): quegetCleanHtml()preserva as caixas.c2f-dyn-boxe os atributosdata-c2f-variabledo DOM anotado antes doreconstructOriginal. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-078 - Correções no Live Editor: Trava de Widgets, Submenu do Painel "+" e Isolamento de Estilos (req-078)
Correção 1 — Travar edição/seleção de elementos internos de widgets
-
[x]
resolveEditable(html-editor.js) reconhece.c2f-dyn-boxcomo bloco atômico (element.closest('.c2f-dyn-box')→ retorna a caixa), paridade com.conn2flow-widget-wrapper. -
[x] CSS (
injectStyles):.c2f-dyn-box{user-select:none}+.c2f-dyn-box *{pointer-events:none!important;user-select:none!important}deixam o conteúdo interno (texto/imagem/links do widget) inerte a clique/seleção.
Correção 2 — Painel "+" expande a categoria sem fechar/roubar o clique
-
[x] Causa-raiz:
#c2f-add-panelfora deisEditorOwned→ o clique em capture do editor usavaelementsFromPoint, atravessava o painel, selecionava o conteúdo atrás e faziastopPropagation(), matando otoggleWidgetGroup. -
[x]
isEditorOwnedreconhece#c2f-add-panele#c2f-backup-panel(viaclosest) → early-return no clique/hover; o clique propaga normal para o handler do painel (lógica de toggle dodashboard.toolbar.jsinalterada).
Correção 3 — Blindagem de CSS dos controles injetados na página hospedeira
-
[x]
injectStyles: hardening com!importantdecolor/background/-webkit-text-fill-color/font/caret-colorem#html-editor-floating-toolbar .he-tb-btn(+ ícones<i>ehe-tb-deselect),#html-editor-tailwind-styler(+input) e#html-editor-modal textarea,input[type="text"],label. -
[x]
!importantno container do styler não vaza para filhos com cor própria (herança CSS não propaga!important) → tags/rótulos coloridos preservados.
Cache-bust
-
[x] Live:
dashboard.toolbar.jscarregainterface/html-editor.js?v=c2f1→?v=c2f2. -
[x] Admin:
biblioteca-html-editor1.3.30→1.3.31(html-editor.php).
Evidência de Validação (BATCH-078)
Rodada 1 (R1)
Evidência automatizada reportada pelo executor em 2026-07-10 (ambiente: PHP 8.4.8):
-
node --check→ OK (2/2):gestor/assets/interface/html-editor.js,gestor/modulos/dashboard/dashboard.toolbar.js(garante que a template literal do CSS injetado fecha corretamente). -
php -l→ OK (2/2):gestor/bibliotecas/html-editor.php,gestor/modulos/dashboard/dashboard.php. -
composer test→ OK (76 tests, 287 assertions, 4 skipped gated por banco); a únicaPHPUnit Deprecationé pré-existente e alheia a este slice. Sem regressão. -
Sem teste unitário novo: slice de UI/CSS (precedente BATCH-066/068). As correções 1 e 2 são reconhecimento de classe via
closest(baixo risco); a 3 é CSS. InstanciarHtmlEditorClassem happy-dom exigiria jQuery + bootstrap pesado doinit()(frágil, jQuery ausente no node_modules); o motor de mapeamento já foi coberto no BATCH-077. -
Decisão registrada: DEC-080.
-
Arquivos:
gestor/assets/interface/html-editor.js(isEditorOwned,resolveEditable,injectStyles);gestor/modulos/dashboard/dashboard.toolbar.js(cache-bust);gestor/bibliotecas/html-editor.php(versão).
Rodada 2 (R2) — Widgets Sem Wrapper, Aparência e Ícones SVG (2026-07-10)
-
[x] R2-P4 (Widget Sem Wrapper): Mapeamento de elementos-raiz do render do widget com atributos
data-c2f-widget-id/root/markerem vez de criar um contêiner.c2f-widget-box(preservando herança e seletores CSS do site hospedeiro). -
[x] R2-P4 (Reconstrução):
reconstructOriginalreconstrói o marcador original a partir do elemento marcado comdata-c2f-markere remove os elementos irmãos do mesmo grupo. -
[x] R2-P1 (Proteção Interna):
resolveEditablereconhece[data-c2f-widget-id]como atômico e o CSS injetado desabilita ponteiros/seleção nos nós internos (pointer-events: none,user-select: none). -
[x] R2-P1 (Outline e Label): Exibição visual do widget via
outline: 1px dashed #fbbf24!importante label absoluto flutuante::before(identificando tipo e slug do widget) sem interferir no fluxo/layout da página (utilizaposition: relative). -
[x] R2-P2 (Atalho Admin): Botão
#he-tb-widget-adminadaptado para identificardata-widget-typeunificando o tratamento de wrappers clássicos e os novos elementos-raiz do live editor. -
[x] R2-P3 (Ícones SVG Inline): Substituição de tags
<i class="... icon">do Fomantic por SVGs inline embutidos no floating toolbar (9 botões) e no styler, garantindo que apareçam em qualquer site público independente das fontes da UI administrativa. -
[x] Cache-Bust: Query-string atualizada para
?v=c2f3(dashboard.toolbar.js) e biblioteca setada para1.4.0(html-editor.php).
Evidência de Teste R2:
-
Criado e executado o script de smoke test
_smoke_batch078_r2.mjsemhappy-domsimulando a carga do live editor, mapeamento de widget sem wrapper, anotação de atributos fora do widget e salvamento (reconstruct). -
Resultado: 18/18 checks aprovados (PASS) sem qualquer vazamento de atributos ou tags de wrapper no HTML reconstruído.
-
composer testmantido verde (76/76 testes aprovados).
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Coree sincronizar (o novohtml-editor.js/dashboard.toolbar.jse a versão da biblioteca só refletem após o deploy; limpar cache do navegador ajuda, embora o?v=c2f3já force o reload no live). -
Widgets: entrar em modo de edição e confirmar que widgets (como menus e destaques) aparecem com outline amarelo tracejado e label identificador no topo ao passar o cursor, e que seus elementos internos não podem ser focados/editados.
-
Painel "+": clicar no "+" da toolbar, clicar no grupo "Menus" e confirmar que o submenu expande sem fechar o painel.
-
Estilos e Ícones: confirmar que os ícones do floating toolbar aparecem perfeitamente renderizados e que os campos/textareas no modal de edição exibem fontes com contraste correto e legível, livre de herança do CSS do site.
-
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-079 - Mapeamento no Pai de Widgets Múltiplos, Image Picker, Filtro/Agrupamento de Módulos e Backups Página×Layout (req-079)
-
[x] Item 1+7 — Marcadores preservados + mapeamento no PAI (marker-based, ver adendo DEC-081):
gestor_pagina_widgetsmantém os comentários<!-- widgets#SIG < --> … > -->no DOM vivo quandogestor_dashboard_toolbar_ativo();mapTreedelimita cada widget pela fronteira exata desses comentários (sem heurística de alinhamento) — marca oliveParent(data-c2f-widget-parent) quando o widget é o único conteúdo do contêiner, senão os elementos-raiz;reconstructOriginalsubstitui oinnerHTMLdo pai pelo marcador cru (preserva<nav>/<ul>). Widgets duplicados/consecutivos ficam separados. Guarda contra marcar a raiz editável. -
[x] Item 2 — Ícones SVG: helper
svgIcon()substitui as<i class="… icon">restantes emhtml-editor.js(accordiondropdown, bgimagefolder open/trash, botõeskind:'icon'do styler). -
[x] Item 3 — Image picker no modal do live editor: botão
_html-editor-imagepick-btnao lado do#element-src;openLiveImagePickermonta iframe →admin-arquivos/?paginaIframe=sime a seleção preenche o input (raizvia construtor). -
[x] Item 4 — Modal redimensionável:
resize:both;overflow:auto+ min/max na caixa do modal fallback. -
[x] Item 5 — Filtro de módulos:
#c2f-modules-filterno topo do dropdown + listenerinput(case-insensitive) emdashboard.iframe-toolbar.js. -
[x] Item 6 — Agrupamento por categoria:
dashboard_site_toolbar_menuagrupa pormodulos_grupos(cabeçalhos.c2f-group-header+ itens.c2f-menu-item); o filtro oculta cabeçalhos de grupos vazios. -
[x] Item 8 — Backups Página × Layout: backend retorna
page_backups/layout_backupsebackup-getaceitatype=page|layout; frontend com 2 colunas e restauração independente (layout preserva o#c2f-page-contentvivo).
Evidência de Validação (BATCH-079)
Reportada pelo executor em 2026-07-10 (PHP 8.4.8). Rodada 2 (marker-based) após teste visual do Chefe (um <nav> com dois menu-header-padrao idênticos ainda marcava o <a>):
-
node --check→ OK:dashboard.toolbar.js,dashboard.iframe-toolbar.js,html-editor.js. -
php -l→ OK:gestor.php,dashboard.php,html-editor.php. -
Vitest
tests/Unit/JS/dashboard.toolbar.test.js(happy-dom, carrega odashboard.toolbar.jsreal via hook injetado) → 3/3 specs:-
Cenário A: widget único é o único conteúdo do
<nav>→ marca o PAI, comentários removidos do vivo, reconstrução porinnerHTMLcom o mockup cru e a tag<nav>preservada. -
Cenário B: 2 widgets idênticos consecutivos no MESMO
<nav>→ 2data-c2f-widget-iddistintos (nav não vira parent), reconstrução com 2 marcadores. -
Cenário C: widget + rodapé estático no mesmo contêiner → widget por-elemento, rodapé preservado, 1 marcador.
-
-
composer test→ 76/76 (287 assertions, 4 skipped) sem regressão. -
npm run test(vitest) → 6/6 total aprovados (incluindo as 3 specs do live editor e 3 widgets legados). -
Cache-bust:
biblioteca-html-editor1.4.1→1.4.2.
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Core+ limpar cache (odashboard.toolbar.js/gestor.phpmudaram; hard-refresh no navegador). -
Item 1/7: abrir uma página com um menu de links (widget) que é o único conteúdo de um
<nav>e confirmar que o outline amarelo envolve todo o<nav>com um único label; num<nav>com dois menus idênticos, confirmar dois widgets independentes. -
Item 2: confirmar que todos os ícones do styler/bgimage/accordion renderizam no live editor (sem Fomantic).
-
Item 3/4: editar uma imagem, abrir o selecionador, escolher um arquivo do
admin-arquivose ver a URL preencher o#element-src; redimensionar o modal pelo canto. -
Item 5/6: abrir o dropdown de módulos, ver as categorias e filtrar por texto (cabeçalhos vazios somem).
-
Item 8: abrir o painel de backups e confirmar as 2 colunas; restaurar um backup de layout preservando o conteúdo vivo, e um de página sem afetar o layout.
-
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-080 - Integração de Modelos de Sessão e Assistente IA no Live Editor (req-080)
-
[x] Fix BATCH-079 — widget atômico:
resolveEditableresolve qualquer elemento do grupo para a raiz (data-c2f-widget-root);positionOverlay/updateSelectionUIusam a união dos bounding boxes (elementRect/unionRect); CSS marca todos os[data-c2f-widget-id]. Não se seleciona link a link; o outline cobre o widget inteiro. -
[x] Item 1/2 — Modelos: botão
.he-tb-templates(só no live), painel#c2f-tpl-panelcom busca#modelos-search-input(debounce), select de framework, relação Substituir/Antes/Depois, grid#modelos-cardspaginado;insertTemplateinsere HTML no DOM vivo + CSS em<style id="c2f-templates-css">. AJAXsite-toolbar-templates-load. -
[x] Item 3 — Assistente IA: botão
.he-tb-ai, painel#c2f-ai-panel(abas Prompt/Modo/Config), selects viasite-toolbar-ia-init(ia_editor_dados), texto de prompt/modo viasite-toolbar-ia-prompt/-ia-mode, geração viasite-toolbar-ia-request;applyAiResulttroca o elemento + injeta CSS. -
[x] Item 4 — Background picker:
requestBackgroundImageno live usaopenLiveImagePicker(imagePickerTarget='background');bindLiveImagePickerroteia p/applyBackgroundImage..he-bgimage-clear→clearBackgroundImage. -
[x] Item 5 — Backend: 5 rotas
site-toolbar-*nodashboard.phpreusandohtml-editor.php/ia.php;ia_editor_dadosnovo; busca de templates retrocompatível.
Evidência de Validação (BATCH-080)
Reportada pelo executor em 2026-07-10:
-
node --check→ OK:html-editor.js,dashboard.toolbar.js. -
php -l→ OK:dashboard.php,ia.php,html-editor.php. -
Vitest
npm run test→ 11/11 (4 arquivos); novotests/Unit/JS/html-editor.live.test.js→ 5/5: botões Modelos/IA presentes só no live (comraiz) e ausentes no admin; painéis Modelos e IA abrem;resolveEditablede qualquer link do grupo → raiz (widget atômico);requestBackgroundImageroteia p/background. -
composer test→ 76/76 (287 assertions, 4 skipped) sem regressão. -
Cache-bust:
interface/html-editor.js?v=c2f4→?v=c2f5+biblioteca-html-editor1.4.2→1.4.3.
Pendências Runtime (com o operador)
-
Deploy
?️ Projects - Update => Core+ hard-refresh (ohtml-editor.js/dashboard.php/ia.phpmudaram). -
Modelos: selecionar um elemento, abrir Modelos, buscar/paginar, escolher "Inserir depois" e ver a seção com CSS aplicado no DOM vivo.
-
IA: abrir o Assistente IA (exige conexão configurada em
servidores_ia), dar uma instrução curta, gerar e ver o elemento alterado na hora. -
Background: no styler,
.he-bgimage-pickabre o gerenciador de arquivos e aplica a imagem comobackground-image;.he-bgimage-clearremove. -
Widget atômico: no
<nav>com 2 menus idênticos, cada widget seleciona como um bloco só (outline cobrindo os 7 links, um label), sem selecionar link a link. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-081 - CodeMirror no Assistente IA, Correção no Save, Dropdowns da Toolbar e Painel "+" em Duas Colunas (req-081)
-
[x] §1 — CodeMirror + resize no Assistente IA:
initAiCodeMirrorinstancia CodeMirror (markdown) em#c2f-ai-instruction/#c2f-ai-mode-textquandowindow.CodeMirrorexiste (dedup por.CodeMirrorirmão), com helpersaiGet/aiSet(fallback ao textarea) usados porsubmitAi/loadAiInit/handlers;dashboard.toolbar.jscarregamode/markdown+mode/javascript. CSS.c2f-he-live-box{resize:both;overflow:auto}(Modelos e IA redimensionáveis). -
[x] §2 — Save intermitente (causa-raiz) + deseleção: blindagem do corpo AJAX no
gestor.php(ob_start/ob_end_clean+JSON_INVALID_UTF8_SUBSTITUTE) elimina o corpo não-JSON por warning/notice espúrio (origem do.catch→ "Erro ao salvar a página." sem erro de rede/log). Cliente (dashboard.toolbar.js):deselectAll()antes dogetCleanHtml, guarda de prontidão do editor e parse tolerante com diagnóstico. NovodeselectAll()nohtml-editor.js. -
[x] §3 — Dropdowns de Usuário e Página: 2 HTMLs (pt-br/en) com dropdowns clicáveis; Usuário (
@[[usuario#nome]]@+ Perfil/Sair); Página (#page_title#+ Editar Página/Avançado + Criar Nova/Clonar dinâmicos publisher×admin resolvidos emdashboard_site_toolbar()); toggle/altura emdashboard.iframe-toolbar.js. -
[x] §4 — CRUD de prompts: botões
ai-prompt-new/edit/del/clear+ handlers reusando 3 rotas novassite-toolbar-ia-prompt-new/-edit/-del(→ia_ajax_prompt_novo/_edit/_del); select atualizado após cada operação. -
[x] §5 — Código Customizado: item no painel "+" →
openCustomCodePanel()(CodeMirror htmlmixed) →insertCustomHtml()insere no DOM vivo;#c2f-custom-panelemisEditorOwned. -
[x] §6 — Painel "+" 2 colunas: Elementos × Widgets (subcolunas grupos × itens), clique no grupo, autocomplete (debounce → AJAX cross-grupo), "Carregar mais"; backend
html_editor_widgets_buscar()(paginação/busca/anti-injection), opçãosite_toolbar.widgets_por_pagina(padrão 10) nodashboard.json; editor clássico inalterado.
Evidência de Validação (BATCH-081)
Reportada pelo executor em 2026-07-11 (ambiente: PHP 8.4.8):
-
php -l→ OK (4/4):gestor/gestor.php,gestor/modulos/dashboard/dashboard.php,gestor/bibliotecas/html-editor.php,gestor/bibliotecas/ia.php. -
node --check→ OK (3/3):gestor/assets/interface/html-editor.js,gestor/modulos/dashboard/dashboard.toolbar.js,gestor/modulos/dashboard/dashboard.iframe-toolbar.js. -
dashboard.json→ JSON válido (comsite_toolbar.widgets_por_pagina). -
Vitest
npm run test→ 14/14 (4 arquivos);tests/Unit/JS/html-editor.live.test.js→ 8/8 (+3 do lote): CRUD de prompts presentes eaiPromptClear;deselectAlllimpa seleção/overlay;openCustomCodePanel+insertCustomHtml(painel montado,isEditorOwned, inserção após a seleção). Stub de CodeMirror emsetup.jsestendido comsetValue/getValuediretos (espelha CM5 real). -
composer test→ 76/76 (287 assertions, 4 skipped) sem regressão (1 PHPUnit Deprecation pré-existente e alheia). -
Cache-bust:
interface/html-editor.js?v=c2f7→?v=c2f8;biblioteca-html-editor1.4.6→1.4.7;dashboard.jsonversao1.0.8→1.0.9.
Pendências Runtime (com o operador)
-
Deploy
?️ Projects - Update => Core+ hard-refresh (mudaramgestor.php,dashboard.php,html-editor.php,ia.php, os 2 HTMLs do toolbar,dashboard.jsone os JS do live/toolbar). -
§1: abrir o Assistente IA e confirmar CodeMirror nos campos de instrução/modo e a caixa redimensionável pelo canto.
-
§2: reproduzir o cenário de save (editar e salvar sem mudar nada, repetidas vezes) e confirmar que não há mais o alerta intermitente "Erro ao salvar a página."; salvar com elemento selecionado/hover ativo e confirmar sucesso.
-
§3: abrir os dropdowns de Usuário (Perfil/Sair) e Página (Editar/Avançado/Criar Nova/Clonar), validando os links dinâmicos publisher×admin e o nome do usuário.
-
§4: criar/editar/excluir um prompt pelo painel do assistente e ver o select refletir.
-
§5: inserir um bloco via "Código Customizado" e vê-lo entrar no DOM vivo.
-
§6: no painel "+", validar as duas colunas, grupos×itens, o autocomplete e o "Carregar mais" (limite configurável).
-
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-082 - Carregamento de Widgets, Seleção de Modelos, Restauração de Backups e Isolamento Multi-usuário no Live Editor (req-082)
-
[x] §1 — Widget dinâmico: rota
site-toolbar-widget-render→dashboard_ajax_site_toolbar_widget_render()(delega ahtml_editor_ajax_widget_render()); listener dedicado nodashboard.toolbar.jsintercepta a string JSONc2f-he:widget-render, faz POST na rota e posta de voltac2f-he:widget-rendered(o motor chamaapplyWidgetRender). -
[x] §2 — Seleção do modelo:
insertTemplaterastreia o 1º nó de elemento (nodeType===1) nas 3 relações (replace/before/after) e o seleciona (selectElement). -
[x] §3 — Restauração de backups:
dashboard_site_toolbar_boxes_widgetsembrulha widgets em<!-- widgets#SIG < -->{render}<!-- widgets#SIG > -->; novodashboard_site_toolbar_resolver_variaveis(valor puro, sem.c2f-var-box);backup-getdevolveraw;restorePageBackup/restoreLayoutBackupre-injetam html+raw, re-rodammapTreee chamamrestoreChrome(varMap preservado — DEC-084 §3). -
[x] §4 — Isolamento multi-usuário (hook core↔projeto): o core só emite o filtro
dashboard/site-toolbar.permissao-pagina(helperdashboard_site_toolbar_verificar_permissao_pagina→hook_apply_filters, defaulttrue) nas rotasrender/save/backups(selecionamid_usuarios) ebackup-get(valida a página do contexto viapage_id). O handler que aplica o isolamento vive no projeto (conn2flow-site:multiusuario.hooks.php+hooks.json).
Evidência de Validação (BATCH-082)
Reportada pelo executor em 2026-07-13 (ambiente: PHP 8.4.8):
-
php -l→ OK:gestor/modulos/dashboard/dashboard.php,gestor/bibliotecas/html-editor.php(core);gestor/project/hooks/controllers/multiusuario.hooks.php(conn2flow-site). -
JSON válido:
conn2flow-site/.../project/hooks/hooks.json(registrocontrollers.dashboard+filters.dashboard["site-toolbar.permissao-pagina"]). -
node --check→ OK:gestor/assets/interface/html-editor.js,gestor/modulos/dashboard/dashboard.toolbar.js. -
Vitest
npx vitest run→ 19/19 (4 arquivos):-
html-editor.live.test.js→ 10/10 (+2 do lote):insertTemplateseleciona o 1º elemento em replace/before/after; ignora nós de texto e seleciona o 1º ELEMENTO. -
dashboard.toolbar.test.js→ 6/6 (+3 do lote): ponte widget-render→AJAX→widget-rendered (URL/body/postMessage corretos); guarda de assinatura/wrapper vazios (sem fetch);restorePageBackupre-anota o widget (marca no pai, consome comentários).
-
-
composer test→ 76/76 (287 assertions, 4 skipped) sem regressão (1 PHPUnit Deprecation pré-existente e alheia). -
Cache-bust:
interface/html-editor.js?v=c2f9→?v=c2f10;biblioteca-html-editor1.4.9→1.4.10.
Pendências Runtime (com o operador)
-
Deploy
?️ Projects - Update => Core+ hard-refresh (mudaramdashboard.php,html-editor.php,html-editor.js,dashboard.toolbar.js). -
§1: inserir um widget pelo painel "+" e confirmar que renderiza de imediato (sem ficar em "Carregando widget…").
-
§2: adicionar um modelo e confirmar que o 1º elemento vem selecionado (substituir/antes/depois).
-
§3: restaurar backups de página e de layout e confirmar que os widgets/variáveis continuam selecionáveis/interativos (sem
.c2f-widget-boxmorta) e que o save posterior preserva marcadores. -
§4: deploy do projeto
conn2flow-site(para sincronizarhooks.json→ tabelahooksviahooks_registrar_projeto, senão o filtro não é carregado em runtime). Depois, logar como usuário restrito e tentar editar/salvar/restaurar backup de página de outro proprietário — confirmar o bloqueio (mensagem "Sem permissão…"); e como admin (acesso completo) confirmar acesso total. No core (sem o filtro registrado) o comportamento é permissivo (defaulttrue). Cobertura automatizada não incluída (o handler é de projeto privado). -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-083 - Correções de Homologação do Live Editor: Hover dos Dropdowns, Preview de Dispositivo Fiel e Normalização de Variáveis no Save
-
[x] §1 — Hover dos dropdowns (hover-intent):
registerHoverDropdownunificado nos 3 dropdowns (c2f-toolbar-menu/c2f-page-dropdown/c2f-user-dropdown); caixa forçada visível por JS (c2f-dropdown-force-open) antes de medir; fechamento adiado 220ms cancelável;window.resizereajusta a altura. CSS.c2f-dropdown-force-open{display:block!important;}nos 2 HTMLs. -
[x] §2 — Preview de dispositivo fiel:
setEditScreenrenderiza o conteúdo num IFRAME (#c2f-device-preview) com a largura do device (media queries/vw-vh/resize reais);srcdoccom CSS do site +<base href>, sem scripts; Desktop edita in-place, Tablet/Mobile é preview não-editável (editor desabilitado); alternar device só troca a largura. -
[x] §3 — Normalização de variáveis/widgets no save: passe final em
reconstructOriginalnormaliza[[x]]→@[[x]]@(idempotente), cobrindo variáveis e widgets inline digitados.
Evidência de Validação (BATCH-083)
Reportada pelo executor em 2026-07-13 (ambiente: Node/Vitest):
-
node --check→ OK:gestor/modulos/dashboard/dashboard.iframe-toolbar.js,gestor/modulos/dashboard/dashboard.toolbar.js. -
dashboard.json→ JSON válido (versao1.0.10). -
Vitest
npx vitest run→ 20/20 (4 arquivos);dashboard.toolbar.test.js→ 7/7 (+1 do lote): normaliza[[pagina#url-raiz]]/[[widgets#promo]]→@[[…]]@, mantém@[[usuario#nome]]@sem duplicar o cerco, não deixa variável sem cerco. -
Sem mudança de PHP neste lote (não há
php -l/composer testnovos; a suíte PHP permanece 76/76 do BATCH-082). -
Cache-bust:
dashboard.jsonversao1.0.9→1.0.10(bustadashboard.toolbar.js/dashboard.iframe-toolbar.js).
Pendências Runtime (com o operador)
-
Deploy
?️ Projects - Update => Core+ hard-refresh (mudaramdashboard.toolbar.js,dashboard.iframe-toolbar.js, os 2 HTMLs edashboard.json). -
§1: redimensionar a janela e confirmar que os 3 dropdowns permanecem abertos ao mover o mouse do trigger para a caixa (sem sumir); testar alternância entre dropdowns.
-
§2: alternar Desktop/Tablet/Mobile e confirmar que o layout responsivo (media queries) muda de verdade; voltar ao Desktop e confirmar a edição in-place ativa.
-
§3: digitar
[[pagina#url-raiz]]e um widget inline no editor, salvar e confirmar que o banco grava@[[…]]@(junto das variáveis existentes) e a página renderiza o valor. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-084 - Preservação de Datas Customizadas (data_criacao/data_modificacao) na Compilação de Recursos (req-084)
-
[x] Modificação no compilador (
atualizacao-dados-recursos.php):-
[x] Implementar mapeamento condicional usando
isset()para as chavesdata_criacaoedata_modificacaodentro decoletarRecursos(). -
[x] Garantir que se a chave não existir no JSON fonte, ela não seja incluída no array compilado final (evitando popular com nulo).
-
[x] Cobrir os 10 recursos detalhados: layouts, componentes, paginas, templates, variaveis, ai_prompts, ai_modes, ai_prompts_targets, forms e widgets.
-
-
[x] Validação:
-
[x] Sintaxe PHP (
php -l) limpa no arquivo alterado. -
[x] Teste unitário verificando a compilação de dados com e sem as chaves customizadas de data (garantir que chaves ausentes não virem nulas).
-
[x] Teste completo da suite (
composer test) sem regressões.
-
Evidência de Validação (BATCH-084)
Evidência automatizada reportada pelo executor e validada em 2026-07-13:
-
✅
php -l gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php→ Sem erros de sintaxe (OK). -
✅
composer test→ 76 testes, 287 assertions (Todos aprovados), garantindo que não houve nenhuma regressão na compilação ou na suíte de testes existente do compilador/descompilador. -
✅ Inspeção manual das mudanças nos 15 pontos de injeção condicional no
coletarRecursos(), validando queisseté usado corretamente e chaves ausentes não populamnullno array resultante.
BATCH-085 - Restauração de Backup Server-Side e Preview de Dispositivo com JS do Site (Live Editor)
-
[x] §1 — Restauração de backup server-side: rota
site-toolbar-backup-restoregravagestor_sessao_variavel('site-toolbar-backup-restore',{id,type,caminho})(valida permissão/propriedade); roteadorgestor_site_toolbar_backup_aplicar()consome a sessão (page load normal + logado), casa o caminho, substitui html da página/layout pelo backup (render pipeline normal + override dev-env) e setagestor.siteToolbarBackupRestaurado; iframe reentra em edição viawindow.parent.gestor. Removidas as funções client-siderestorePageBackup/restoreLayoutBackup/remapAfterRestore. -
[x] §2 — Preview de dispositivo com JS do site:
enterDevicePreviewcarrega a URL real (?c2f-device-preview=1) em vez dosrcdocsó-CSS;gestor_dashboard_toolbar_ativo()desativa a toolbar com esse param (mantém layout/CSS/JS reais → menu hambúrguer/interações funcionam).
Evidência de Validação (BATCH-085)
Reportada pelo executor em 2026-07-13 (ambiente: PHP 8.4.8, Node/Vitest):
-
php -l→ OK:gestor/gestor.php,gestor/modulos/dashboard/dashboard.php. -
node --check→ OK:gestor/modulos/dashboard/dashboard.toolbar.js,gestor/modulos/dashboard/dashboard.iframe-toolbar.js. -
dashboard.json→ JSON válido (versao1.0.11). -
Vitest
npx vitest run→ 19/19 (removido o teste derestorePageBackup, agora obsoleto com a nova abordagem server-side). -
composer test→ 76/76 (287 assertions, 4 skipped) sem regressão.
Pendências Runtime (com o operador)
-
Deploy
?️ Projects - Update => Core+ hard-refresh (mudaramgestor.php,dashboard.php,dashboard.toolbar.js,dashboard.iframe-toolbar.js,dashboard.json). -
§1: restaurar backup de página e de layout no editbar; confirmar reload + reentrada automática em edição já com o backup renderizado, e que o save persiste o backup. Testar isolamento multi-usuário (backup de outro dono → bloqueio).
-
§2: no preview Tablet/Mobile, confirmar que o menu hambúrguer e demais interações JS do site funcionam e o layout responsivo é fiel. (Reflete a versão salva; edições não salvas voltam ao alternar para Desktop.)
-
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-086 - Preservação de data_modificacao no Sincronizador de Banco de Dados (req-086)
-
[x] Modificação no sincronizador (
atualizacoes-banco-de-dados.php):-
[x] Implementar a injeção forçada de
data_modificacaono array$diffcaso ela exista no registro de entrada e no schema da tabela e uma divergência seja encontrada no update. -
[x] Cobrir os 3 pontos: Modo PK, Modo Chave Natural e modo Fallback Chave Natural.
-
-
[x] Validação:
-
[x] Sintaxe PHP (
php -l) limpa no arquivo alterado. -
[x] Validação funcional mostrando que a data de modificação original do JSON é mantida após sincronização de alteração.
-
[x] Teste completo da suite (
composer test) sem regressões.
-
Evidência de Validação (BATCH-086)
-
✅
php -l→ OK. -
✅
composer test→ 76 testes, 287 assertions (Todos aprovados). -
✅ Deploy e sincronização realizados com sucesso pelo operador. A
data_modificacaomantida no JSON foi gravada na base de dados, sem ser sobrescrita pelo timestamp da execução.
BATCH-087 - Parametrização e Resumo de Órfãos no Sincronizador de Banco de Dados (req-087)
-
[x] Modificação no sincronizador (
atualizacoes-banco-de-dados.php):-
[x] Retornar contagem de órfãos na chave
'orphans'na funçãosincronizarTabela(). -
[x] Silenciar logs individuais (
ORPHAN_DB_ROWeORPHAN_DB_ROW_NAT) exigindo a presença de--orphans-detailna CLI. -
[x] Alterar padrão de exportação de órfãos (
$orphansMode) para'ignore'. A gravação física em disco exige--orphans-mode=export. -
[x] Atualizar
relatorioFinal()para imprimir a quantidade de órfãos na tabela por recurso e a soma total consolidada.
-
-
[x] Modificação na atualização do sistema (
atualizacoes-sistema.php):-
[x] Propagar as flags
'orphans-detail'e'orphans-mode'no whitelist deexecutarAtualizacaoBanco().
-
-
[x] Validação:
-
[x] Sintaxe PHP (
php -l) limpa nos dois arquivos alterados. -
[x] Validação visual do novo sumário sem geração de arquivos JSON ou logs individuais de órfãos no console.
-
[x] Reativação completa do log individual e exportações via flags CLI.
-
[x] Teste completo da suite (
composer test) sem regressões.
-
Evidência de Validação (BATCH-087)
Evidência automatizada e estática validada em 2026-07-15:
-
✅ Lint estático de banco de dados (
php -l atualizacoes-banco-de-dados.php) → OK. -
✅ Lint estático de sistema (
php -l atualizacoes-sistema.php) → OK. -
✅
composer test→ 76 testes, 287 assertions (Todos aprovados). -
✅ Validação visual: o relatório final agora inclui
(órfãos: X)para cada tabela e a soma total consolidada| Órfãos Totais: Y, e o comportamento padrão silencioso não gerou arquivos JSON ou logs individuais desnecessários.
BATCH-088 - Módulos/Widgets "forms-search" (Formulários de Busca) e "pages-index" (Páginas Índice) (req-088)
-
[x] Módulo
forms-search:-
[x] Copiado de
forms/paraforms-search/com substituições de nomes de variáveis, slugs, ids, tabelas e arquivos (via placeholders para desambiguarforms_searchda tabela/funções vsforms-searchdo módulo/arquivos). -
[x] O formulário público usa o método
GET(forms_search_widget_forcar_get) e garante o inputname="search"(forms_search_widget_garantir_campo_search). -
[x] O action é dinâmico (
fields_schema.form_actionvia campo#form_actiondo CRUD) e aponta para a página alvo; defaultbusca/(forms_search_resolver_action). Sem controlador POST/reCAPTCHA. -
[x] Helper
forms_search_registrar_busca()grava o termo emforms_search_submissions.
-
-
[x] Módulo
pages-index:-
[x] Copiado de
publisher-index/parapages-index/com substituições de slugs e nomenclatura. -
[x] Consulta DIRETA a
paginas(status='A' AND language='$language' AND tipo='pagina' AND sem_permissao=1), sem JOIN empublisher_pages. -
[x] Busca filtra
nome/html(nome LIKE '%termo%' OR html LIKE '%termo%'); ordenaçãotitle_asc/desc,date_asc/desc(data_modificacao). -
[x] Busca alimentada inicialmente pela variável GET
search(page load) e refletida no input via[[search]]. -
[x] Mapeamento padrão fornece
[[item#title]](nome),[[item#summary]](strip_tags(html)~200 chars),[[item#url]](url-raiz+caminho) e[[item#date]](bônus). -
[x] Página semente pública criada e registrada (caminho
busca/— ver DEC-089 §nota;pages-index/é a rota admin do módulo). Widget aponta para índicegrupo_slug="padrao".
-
-
[x] Migração do Banco:
-
[x]
20260715120000_create_forms_search_and_pages_index_tables.phpcriaforms_search,forms_search_submissionsepages_index(índices únicos[id, language]+down()reversível).
-
-
[x] Validação:
-
[x] Sintaxe PHP (
php -l) e JS (node --check) limpa em todos os novos arquivos. -
[x] Execução bem-sucedida de
composer testno core, sem regressões.
-
Evidência de Validação (BATCH-088)
Evidência automatizada reportada pelo executor em 2026-07-15 (ambiente: PHP 8.4.8):
-
php -l→ OK (5/5):pages-index.php,pages-index.widget.php,forms-search.php,forms-search.widget.php, migração20260715120000. -
node --check→ OK (4/4):pages-index.js,pages-index.widget.js,forms-search.js,forms-search.widget.js. -
JSON válido → OK (4/4):
pages-index.json,forms-search.json,ModulosData.json,UsuariosPerfisModulosData.json. -
Teste novo
tests/Unit/PHP/PagesIndexFormsSearchWidgetTest.php→ OK (14 tests, 27 assertions): resumo (strip_tags/truncamento/reticências), render de itens ([[item#X]] + variable_mapping), blocos condicionais/globais, resolução de action (vazio→busca/, relativo, absoluto), força demethod=get+action e garantia/idempotência do camponame="search". -
composer test(suíte completa) → OK (90 tests, 314 assertions, 4 skipped) — era 76; +14 deste lote, sem regressão (a únicaPHPUnit Deprecationé pré-existente).
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Core(aplica a migração Phinx, gera os*Data.jsone recalcula checksums) e confirmar: as 3 tabelas criadas; os 2 módulos listados; os 2 widgets (pages-index/forms-search) na tabelawidgets; a páginabusca/gerada. -
Criar o índice padrão
pages_indexcomid='padrao'(CRUDpages-index/adicionar/) e um template, para a página sementebusca/renderizar resultados (o widget usagrupo_slug="padrao"). -
Validar o fluxo ponta a ponta: form
forms-search(GET) envia?search=termoparabusca/; a página exibe as páginas casadas e o termo é gravado emforms_search_submissions. -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-090 - Transição do Gerenciador de Arquivos para Árvore Física e CRUD de Diretórios (req-090)
-
[x] Segurança (biblioteca pura):
-
[x]
bibliotecas/arquivo.phpcomarquivo_nome_sanitizar,arquivo_extensao_perigosa,arquivo_caminho_relativo_seguro,arquivo_caminho_resolver,arquivo_mini_caminho_relativo,arquivo_tipo_por_extensao(versão 1.1.0). -
[x] Todas as rotas do backend validam a entrada por esses helpers antes de tocar o disco (path traversal, extensão perigosa, sanitização de nome).
-
-
[x] Banco: migração
20260717120000_create_arquivos_disco_categorias_table.php(nova tabelaarquivos_disco_categorias, índice único[caminho_hash,id_categorias],down()reversível).arquivos/arquivos_categoriaslegadas preservadas. -
[x] Backend (
admin-arquivos.php): rotaslistar(varredura física paginada/ordenada/filtrada + breadcrumb + thumbsMissing),uploadFile(destino, sanitização, bloqueio de extensão, colisão, mini imediata, categorias por caminho),miniaturas(lote SimpleImage),excluir(lote + pasta recursiva + limpeza de mini/associações),pasta-criar,renomear(move associações),categorias-arquivo. -
[x] Frontend (
admin-arquivos.js): 4 modos de visualização (localStorage), breadcrumb navegável, miniaturas lazy em lote com barra de status + cache-bust, seleção em lote + exclusão em massa, CRUD de pastas, filtros; upload com drag&drop, seletor de tamanho de preview e pasta de destino; bloqueio client-side de extensão. -
[x] Views/i18n:
admin-arquivos.html/admin-arquivos-adicionar.html+ CSS (pt-br + en) reescritos; ~24 variáveis novas por idioma;admin-arquivos.json1.0.4 → 1.1.0 (configlista/upload). -
[x] Retrocompat Image Picker (
interface.php):imagepickresolve identificador não-numérico como caminho físico (metadados do disco + miniatura preferida com cache-bust); IDs numéricos legados via tabelaarquivos; picker devolve caminho relativo.
Evidência de Validação (BATCH-090)
Evidência automatizada reportada pelo executor em 2026-07-17 (ambiente: PHP 8.4.8):
-
php -l→ OK (5/5):gestor/bibliotecas/arquivo.php,gestor/modulos/admin-arquivos/admin-arquivos.php,gestor/bibliotecas/interface.php,gestor/db/migrations/20260717120000_create_arquivos_disco_categorias_table.php,tests/Unit/PHP/AdminArquivosSegurancaTest.php. -
node --check gestor/modulos/admin-arquivos/admin-arquivos.js→ OK;admin-arquivos.json→ JSON válido. -
vendor/bin/phpunit tests/Unit/PHP/AdminArquivosSegurancaTest.php→ OK (16 tests, 53 assertions): sanitização de nome (caracteres inválidos, componentes de diretório, bytes nulos), extensões perigosas (executáveis, dupla extensão, ocultos de config, extensões seguras), path traversal (relativo válido/rejeita../absoluto/nulo), resolução sob a base (mantém dentro/rejeita escape/aceita alvo inexistente seguro), caminho de miniatura e tipo por extensão. -
composer test→ OK (106 tests, 367 assertions, 4 skipped gated por banco); a únicaPHPUnit Deprecationé pré-existente e alheia a este slice.
Pendências Runtime (com o operador)
-
Rodar
?️ Projects - Update => Core+ migração20260717120000(criaarquivos_disco_categorias; recompila páginas/variáveis do módulo). -
Homologar
/admin-arquivos/: alternar os 4 modos de visualização; criar/renomear/excluir pastas (inclusive pasta não-vazia com confirmação recursiva); navegar por breadcrumb; seleção em lote + exclusão em massa; filtros por data/categoria/ordenação. -
Homologar
/admin-arquivos/adicionar/: drag&drop, seletor de tamanho de pré-visualização, escolha/criação de pasta de destino, upload e geração dinâmica das miniaturas com a barraProcessando miniaturas.... -
Homologar o Image Picker: inserir imagem via iframe num módulo consumidor (ex.: galleries) e confirmar persistência retrocompatível (registro numérico legado renderiza da tabela
arquivos; caminho físico novo renderiza do disco/mini). -
Restrição respeitada: nenhum
git commit/git pushexecutado.
BATCH-091 - Refinamentos de CRUD, Novos Modelos de Lupa e Autocomplete AJAX Otimizado no Módulo "forms-search" (req-091)
-
[x] Módulo
forms-search:-
[x] Removidas as abas "Email" e "Redirects" dos templates de CRUD (adicionar, editar, clonar) e desabilitada a lógica de processamento destas abas no PHP/JS.
-
[x] Renomeada a aba "Campos" para "Campos Extras".
-
[x] Forçada a renderização do input padrão de busca (
name="search") demarcado por<!-- input-search < -->em todos os templates visuais de lupas do widget. -
[x] Redesenhados os 5 templates padrão de lupas / caixas de busca focados na usabilidade de pesquisa textual.
-
-
[x] Autocomplete AJAX no Widget:
-
[x] Novo endpoint AJAX em
forms-search.php/.widget.phpque consulta a tabelapaginas(status = 'A' AND language = '$language' AND tipo = 'pagina' AND sem_permissao = 1). -
[x] Caixa flutuante de resultados (
<!-- results-box < -->) renderizada dinamicamente com limite inicial de 30 páginas e botão "Carregar mais". -
[x] Ao clicar em um item da caixa flutuante, o usuário é redirecionado para a respectiva página.
-
[x] Se o usuário submeter o formulário (Enter ou clique), envia um GET com
?search=termopara o action configurado (defaultbusca/).
-
-
[x] Melhorias de Usabilidade Aprovadas:
-
[x] Debounce de 300ms implementado na digitação para disparar o autocomplete AJAX.
-
[x] Limite mínimo de 3 caracteres para disparar o autocomplete.
-
[x] Navegação na caixa de resultados usando as setas Cima/Baixo e seleção via Enter.
-
[x] Destaque do termo de busca no título/resumo usando a tag
<mark>ou classe negrito. -
[x] Cache local de resultados em memória JS.
-
-
[x] AI Mode:
-
[x] Prompts de IA no
forms-search.jsonadaptados para descrever as novas características de formulário de busca e autocomplete.
-
-
[x] Validação:
-
[x] Sintaxe PHP (
php -l) e JS (node --check) limpa nos novos arquivos. -
[x] Execução com sucesso da suíte completa de testes (
composer test).
-
Evidência de Validação (BATCH-091)
Evidência automatizada reportada em 2026-07-20:
-
Lint estático (
php -lem PHP enode --checkem JS) → OK. -
composer test(PHPUnit) → OK (108 testes, 466 assertions, 4 skipped) — sem regressões. -
npm run test(Vitest) → OK (20 testes, todos aprovados) — contemplando o novoforms-search.widget.test.jspara o frontend. -
Validação no CRUD e nos templates visuais de lupas (células
input-searcheresults-box) corretos.
BATCH-092 - Destaque, Sincronização de URL, Debounce, Cache e Teclado no Módulo "pages-index" (req-092)
-
[x] Destaque Visual (Highlighting):
-
[x] Termo buscado destacado nos títulos (
[[item#title]]) e resumos ([[item#summary]]) dos itens exibidos na listagem dopages-index. -
[x] Marcação gerada dinamicamente com
<mark>de forma case-insensitive no script cliente.
-
-
[x] Integração com URL:
-
[x] No carregamento inicial, se a URL contiver
?search=termo(ou?busca=termo), preenche o input.pages-index-search, executa a busca AJAX e destaca o termo. -
[x] Ao digitar no input
.pages-index-search, atualiza a URL do navegador usandohistory.replaceStatesem recarregar a página.
-
-
[x] Melhorias de Usabilidade no Widget:
-
[x] Debounce de 300ms com cancelamento automático de requisições AJAX pendentes (race condition protection).
-
[x] Cache local em memória JS para consultas repetidas do
pages-index. -
[x] Suporte a navegação por teclado (ArrowUp/ArrowDown) na lista de resultados da página quando o campo de busca estiver focado, e navegação ao pressionar Enter.
-
-
[x] Validação:
-
[x] Sintaxe PHP (
php -l) e JS (node --check) limpa. -
[x] Execução com sucesso da suíte de testes.
-
Evidência de Validação (BATCH-092)
Evidência automatizada reportada em 2026-07-20:
-
Lint estático (
php -lenode --check) → OK. -
composer test(PHPUnit) → OK (110 testes, 474 assertions, 4 skipped) — todos aprovados. -
npm run test(Vitest) → OK (25 testes, todos aprovados) — cobrindo o novopages-index.widget.test.jspara o frontend.
BATCH-093 - Renderização de Variáveis/Widgets no Editor HTML Clássico e Preview (req-093) — complete
-
[x] Backend (
html-editor.php): funções de caixas duplicadas/adaptadas (html_editor_boxes_variaveis/_boxes_widgets/resolver_var/resolver_variaveis/var_box/render_widget_signature) com regex tolerante a[[var]]/@[[var]]@; rotahtml-editor-render-vars→{boxes, values}. Globais resolvidas; locais preservadas literais. -
[x] Frontend (
html-editor-interface.js):htmlEditorRenderVars(AJAX, cb{boxes,values}, fallback ao cru),htmlEditorReconstructVars(reversão caixa→[[var]], no-op sem caixas),editorHtmlVisualasync (globais em caixas antes de abrir), reversão no save (previsualizarConfirmar). -
[x] Preview iframe (
previewHtmlasync): globais resolvidas para valor viavalues; locais via simulação; fallback ao HTML local. -
[x] publisher-pages coberto pela infra genérica (rota resolve globais p/ qualquer módulo; locais preservadas). Editor visual: globais em caixas, locais como marcadores (preservadas no save; sem simulação replicada, que quebraria a reversão 1:1).
-
[ ] Refinamento opcional: variáveis LOCAIS em caixas protegidas 1:1 no editor visual (UX). (futuro; atual já é seguro)
-
[ ] Widgets no clássico (render + reversão em runtime). (validar no deploy)
Evidência de Validação (BATCH-093 — Fase base)
Reportada pelo executor em 2026-07-20:
-
php -l gestor/bibliotecas/html-editor.php→ OK. Smoke CLI das funções de caixas: global em texto →.c2f-var-boxcomdata-c2f-marker; global em atributo → valor; local ([[item#foo]]) → preservada;valuesresolve tudo → OK. -
node --check gestor/assets/interface/html-editor-interface.js→ OK. -
npx vitest run tests/Unit/JS/html-editor-vars.test.js→ 4/4 (extraindo a função REAL): round-trip[[var]], no-op sem caixas, cerco@[[var]]@exato, múltiplas caixas. -
Suíte completa:
npx vitest run29/29,composer test110/110 sem regressão. -
Cache-bust:
biblioteca-html-editor1.4.10→1.4.11.
Pendências
-
Runtime (deploy
Update => Core):-
/admin-paginas/: no preview (#iframe-visualizacao-pagina), confirmar que as variáveis globais aparecem com o valor real; no Editor Visual, ver as globais como caixas de destaque; editar texto, salvar e conferir no banco que a variável ([[…]]/@[[…]]@) foi preservada (não o valor). -
/publisher-pages/: confirmar que as variáveis LOCAIS simuladas e as GLOBAIS aparecem em harmonia no preview; no editor visual, globais em caixas e locais como marcadores; save preserva ambas.
-
-
Restrição respeitada: nenhum
git commit/git pushexecutado.