From 52187a0b2cc0eae8e54e6dbf131051f6f71ef03f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor=20Ribeiro=20Santos?= <60783014+tbc-joaovitor@users.noreply.github.com> Date: Sat, 8 Aug 2026 18:26:51 -0300 Subject: [PATCH] =?UTF-8?q?feat(protheus):=20mem=C3=B3ria=20do=20legado,?= =?UTF-8?q?=20confian=C3=A7a=20rotulada=20e=20gates=20em=20arquivo=20(2.16?= =?UTF-8?q?.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nova skill /protheus:arqueologia — mapeia a fatia do legado que a demanda toca (customizações, Pontos de Entrada, dicionário customizado, regras de negócio) em docs/legado/, append-only e com escala de confiança. Fatia já mapeada é conferida, não remapeada. Fecha o ciclo dos dois lados: /protheus:plan ganha o Passo 3.5 (alcance medido nos callers + lista do que não pode quebrar antes de salvar o plano) e /protheus:verify ganha o gate de regressão (1.6) e o writeback pós-liberação (2.5), que devolve ao mapa o que a entrega criou. Escala CONFIRMADO/INFERIDO/LACUNA no /protheus:specialist, com teto por proveniência (documentação sozinha não passa de INFERIDO), aplicada também no /protheus:diagnose (não corrigir sobre LACUNA) e no /protheus:brainstorm (recomendação com rótulo e fonte). /protheus:brainstorm passa a perguntar por rodadas de fronteira, com a regra "fato é meu, decisão é sua". O gates.json vira um arquivo por feature, criado no brainstorm: plan e implement derivam o estágio do arquivo e retomam de onde pararam. Novo hook advpl-encoding-pre.sh (PreToolUse) bloqueia Edit/Write em fonte CP-1252 antes da leitura destrutiva que corrompe os acentos, com teste na suíte. Aprendizados de campo em writer, reviewer, patterns, query-builder, mvc-generator e feedback. Co-Authored-By: Claude Fable 5 --- .claude-plugin/marketplace.json | 2 +- CHANGELOG.md | 59 ++++++++ README.md | 2 +- protheus/.claude-plugin/plugin.json | 2 +- protheus/CLAUDE.md | 7 +- protheus/README.md | 26 ++-- protheus/hooks/advpl-encoding-pre.sh | 76 +++++++++++ protheus/hooks/hooks.json | 12 ++ protheus/hooks/session-context.cjs | 4 +- protheus/skills/arqueologia/SKILL.md | 137 +++++++++++++++++++ protheus/skills/brainstorm/SKILL.md | 181 ++++++++++++++++++++----- protheus/skills/deploy/SKILL.md | 2 +- protheus/skills/diagnose/SKILL.md | 10 ++ protheus/skills/feedback/SKILL.md | 34 +++++ protheus/skills/implement/SKILL.md | 53 +++++++- protheus/skills/mvc-generator/SKILL.md | 7 + protheus/skills/patterns/SKILL.md | 11 ++ protheus/skills/plan/SKILL.md | 106 ++++++++++++++- protheus/skills/qa/SKILL.md | 2 +- protheus/skills/query-builder/SKILL.md | 7 + protheus/skills/reviewer/SKILL.md | 13 ++ protheus/skills/specialist/SKILL.md | 41 +++++- protheus/skills/verify/SKILL.md | 69 +++++++++- protheus/skills/writer/SKILL.md | 15 +- tests/hooks/advpl-encoding-pre.test.sh | 37 +++++ tests/run-all.sh | 1 + 26 files changed, 835 insertions(+), 81 deletions(-) create mode 100755 protheus/hooks/advpl-encoding-pre.sh create mode 100644 protheus/skills/arqueologia/SKILL.md create mode 100755 tests/hooks/advpl-encoding-pre.test.sh diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 581e998..b21796a 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -30,7 +30,7 @@ "name": "protheus", "source": "./protheus", "description": "Plugin para desenvolvimento TOTVS Protheus — ciclo completo: brainstorm → plan → implement (Agent Teams) → deploy TDS-CLI → qa E2E → verify, geradores MVC/REST/query, dicionário de dados, SmartView/TReports e Knowledge Base remota (155k+ registros).", - "version": "2.15.0", + "version": "2.16.0", "author": { "name": "DataAgile" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ffaeac..87875c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,65 @@ Histórico das versões públicas do `dataagile-agent-kit`. --- +## [2.8.0] — 2026-08-08 + +### O ciclo Protheus passou a lembrar do legado do cliente (protheus 2.16.0) + +Cada demanda começava do zero: ninguém sabia quais customizações já existiam na área que ia +ser mexida, e o que a entrega anterior estabeleceu morria no patch. A nova skill +**`/protheus:arqueologia`** mapeia **a fatia** que a demanda toca — customizações, Pontos de +Entrada, dicionário customizado e regras de negócio embutidas — e grava em `docs/legado/`, +append-only, com escala de confiança. Fatia já mapeada não é remapeada: é **conferida**, e +divergência entre o mapa e o fonte de hoje vira achado. + +Do outro lado do ciclo, o `/protheus:verify` ganhou o **writeback** (Passo 2.5): terminada a +liberação, o que a entrega criou volta para o mapa e para a lista de regressão. O +`/protheus:plan` ganhou o **Passo 3.5**, que mede o alcance real da mudança (`grep` nos +callers, confrontado com a lista fechada de fontes) e escreve o que **não pode quebrar** antes +de salvar o plano — item verificável vira cenário E2E nomeado; item sem forma de verificar é +observação, não regressão. O `/protheus:verify` bloqueia se algum item ficar sem veredito. + +### Confiança rotulada: CONFIRMADO, INFERIDO, LACUNA + +O `/protheus:specialist` passou a exigir **rótulo e fonte em toda afirmação técnica**, com teto +por proveniência: conhecimento destilado de código pode chegar a CONFIRMADO; documentação +sozinha tem teto INFERIDO. Dicionário de dados é INFERIDO até conferir no SX3 do cliente. + +A escala atravessa o ciclo: o `/protheus:diagnose` rotula a causa raiz **antes** de propor +correção e não corrige sobre LACUNA; o `/protheus:brainstorm` recomenda com rótulo e fonte em +cada pergunta. + +### Brainstorm por rodadas, e estado de pipeline em arquivo + +O `/protheus:brainstorm` trocou "uma pergunta por mensagem" por **rodadas de fronteira**: monta +a árvore de decisão, pergunta de uma vez tudo que já dá para perguntar, e só termina quando não +sobra premissa adotada em silêncio. Junto veio a regra **fato é meu, decisão é sua** — o que dá +para descobrir no repositório, no MCP ou no ambiente não vira pergunta ao dev. + +O `gates.json` virou **um arquivo por feature**, criado no brainstorm e alimentado até o verify +(`spec_review` → `code_review` → `lint` → `deploy` → `qa_e2e`). `plan` e `implement` derivam o +estágio **do arquivo**, nunca da conversa: sessão nova retoma de onde parou, e com mais de uma +feature aberta o skill pergunta qual, em vez de escolher a mais recente. + +### Hook que barra a corrupção de acento antes dela acontecer + +`Edit`/`Write` em fonte CP-1252 liam o arquivo como UTF-8 e regravavam com os acentos já +destruídos — o hook pós-gravação avisava depois do estrago. O novo **`advpl-encoding-pre.sh`** +(PreToolUse) bloqueia a ferramenta antes da leitura destrutiva e entrega o script Python que +edita preservando o charset. Coberto por testes na suíte. + +### Aprendizados de campo nas skills + +`writer` e `reviewer`: `FWMsgRun` dentro de `VALID` trava a tela; variável tipada compara com +`Empty()`, não com `NIL` — e `advpls appre` **não** pega erro de tipo, então lint limpo não +garante compilação. O `reviewer` também parou de reportar dois falsos positivos conhecidos em +`.tlpp`. `patterns`: `MsUnlock` sempre com alias explícito, alias já posicionado após +`Posicione()`, e PE bloqueante × PE pós-gravação. `query-builder`: `ORDER BY` com `DESC` por +coluna e alias de subquery sem `AS` (Oracle). `mvc-generator`: MVC em `.tlpp` exige namespace +completo + `U_` nas referências. `feedback`: checagem de duplicata/contradição antes do rascunho +e tag `promote:` no payload. + + ## [2.7.0] — 2026-08-07 ### Brainstorm em opus, implementação em sonnet, haiku só no deploy (protheus 2.15.0 · fluig 2.2.0) diff --git a/README.md b/README.md index 131ecea..be9d34b 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ # DA DataAgile Agent Kit -[![Versão](https://img.shields.io/badge/versão-2.7.0-1a4d5c?style=flat-square&logoColor=white)](https://github.com/tbc-servicos/dataagile-agent-kit/releases) +[![Versão](https://img.shields.io/badge/versão-2.8.0-1a4d5c?style=flat-square&logoColor=white)](https://github.com/tbc-servicos/dataagile-agent-kit/releases) [![Claude Code](https://img.shields.io/badge/Claude_Code-plugin-CC785C?style=flat-square&logoColor=white)](https://claude.ai/code) [![Protheus](https://img.shields.io/badge/Protheus-ADVPL%2FTLPP-1a4d5c?style=flat-square&logoColor=white)](https://dataagile-agent-kit.dataagile.com.br) [![PO--UI MCP](https://img.shields.io/badge/PO--UI-MCP-22C55E?style=flat-square&logoColor=white)](https://po-ui.io) diff --git a/protheus/.claude-plugin/plugin.json b/protheus/.claude-plugin/plugin.json index 6718d60..6c30afe 100644 --- a/protheus/.claude-plugin/plugin.json +++ b/protheus/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "protheus", "description": "Plugin Claude Code para desenvolvimento TOTVS Protheus — ciclo completo: brainstorm → plan → implement (teammates sonnet) → deploy (TDS-CLI) → qa (E2E Playwright) → verify. Geração ADVPL/TLPP, SQL embarcado, migração TLPP, diagnóstico, compilação, revisão, testes E2E Playwright (test-web), Knowledge Base MCP, integração TDN, geradores MVC/REST/query, dicionário de dados e geração de relatórios SmartView/TReports (smartview-relatorio).", - "version": "2.15.0", + "version": "2.16.0", "author": { "name": "TBC - Time de Desenvolvimento" }, diff --git a/protheus/CLAUDE.md b/protheus/CLAUDE.md index 174be57..c5ecf04 100644 --- a/protheus/CLAUDE.md +++ b/protheus/CLAUDE.md @@ -15,6 +15,7 @@ Para código com padrões TOTVS (notação húngara, BeginSQL, ExecBlock, MVC), | Quando você for... | Skill recomendada | |---|---| | Escrever/gerar código ADVPL ou TLPP | `/protheus:writer` | +| Mapear o legado do cliente antes de mexer (customizações, PEs, regras) | `/protheus:arqueologia` | | Planejar uma feature ou novo desenvolvimento | `/protheus:brainstorm` | | Investigar erro, log de compilação, crash | `/protheus:diagnose` | | Revisar código existente | `/protheus:reviewer` | @@ -36,7 +37,7 @@ Custo de código fora do padrão: alto (retrabalho, code review, manutenção). - **Notação húngara:** `c`=char · `n`=numérico · `l`=lógico · `d`=data · `a`=array · `b`=bloco · `o`=objeto - **Escopo explícito:** `Local` / `Static` / `Private` / `Public` — declarar no topo da função, antes de qualquer código -- **Tratamento de erros:** programação defensiva com guard clauses e verificação de retorno; `ErrorBlock` para capturar erros de runtime em chamadas críticas; **nunca usar** `BEGIN SEQUENCE` +- **Tratamento de erros (regra única):** programação defensiva com guard clauses e verificação de retorno; **`Try-Catch` é o padrão em TLPP** (`.tlpp`, classes); `ErrorBlock` **somente** em ADVPL clássico (`.prw`) onde Try-Catch não está disponível; **nunca usar** `BEGIN SEQUENCE` - **Extensões:** `.prw` programa · `.tlpp` TLPP moderno ## Regra de Modelos (OBRIGATÓRIA) @@ -105,7 +106,11 @@ export CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=50 ## Ciclo de Desenvolvimento +> **Entrega de fonte ADVPL/TLPP roda pelos gates deste plugin.** Workflows genéricos +> de entrega não passam por lint/compilação e não gravam `gates.json` — não use. + ``` +/protheus:arqueologia → mapa do legado da fatia (quando não houver) /protheus:brainstorm → MIT044/design aprovado /protheus:plan → plano de implementação com tasks tipadas /protheus:implement → Agent Team (implementer sonnet + reviewers sonnet, worktree) diff --git a/protheus/README.md b/protheus/README.md index 26c5766..dd6cbf3 100644 --- a/protheus/README.md +++ b/protheus/README.md @@ -205,6 +205,7 @@ Reinicie o Claude Desktop depois de salvar. ``` /protheus:init-project → explora projeto, entrevista, gera CLAUDE.md +/protheus:arqueologia → mapa do legado da fatia (quando não houver) /protheus:brainstorm → MIT044 (opcional) + perguntas + design aprovado /protheus:plan → decompõe design em tasks ADVPL-tipadas /protheus:implement → Agent Team (worktree + feedback bidirecional): @@ -226,13 +227,14 @@ Reinicie o Claude Desktop depois de salvar. | Review e QA | **sonnet** | Análise qualitativa, padrões, riscos | | Deploy / compilação | **haiku** | Compilar e gerar patch — mecânico | -## Skills Disponíveis (17) +## Skills Disponíveis (18) ### Ciclo Principal | Comando | Descrição | |---------|-----------| | `/protheus:init-project` | Explora projeto, entrevista e gera `CLAUDE.md` | +| `/protheus:arqueologia` | Mapeia a fatia do legado do cliente antes do design | | `/protheus:brainstorm` | Planeja implementação — MIT044, perguntas, design aprovado | | `/protheus:plan` | Decompõe design em tasks ADVPL-tipadas | | `/protheus:implement` | Agent Team: impl → spec-review → code-review → lint | @@ -297,23 +299,20 @@ Acesso a referência pública ADVPL/TLPP filtrada por organização (row-level v | `searchFunction` | Busca funções ADVPL/TLPP por nome, módulo, tipo | | `findEndpoint` | Encontra endpoints REST por path, método | | `findSmartView` | Busca SmartView por keyword ou equipe | -| `listModules` | Lista módulos com contagem de funções | +| `searchKnowledge` | Busca padrões, templates, convenções e aprendizados registrados | +| `submitFeedback` | Registra um aprendizado de correção na base (via `/protheus:feedback`) | +| `get_skill` | Recupera o conteúdo de uma skill da base | | `ragSearchKnowledge` | Busca vetorial (embedding 1536-dim) sobre uma base de conhecimento técnico ADVPL/TLPP | | `ragSearchDocs` | Busca vetorial sobre documentação técnica TOTVS (TDN), retorna `title`+`source_url`+`product_id` | > Campos `source`, `implementation`, `code` (IP proprietário TOTVS) são removidos das respostas para tier external. A base RAG é uma curadoria técnica sem PII. -### Tier `internal` (TBC — 9 tools) +### Tools adicionais de tier interno -Inclui as 4 do external + 5 internas adicionais: - -| Tool | Descrição | -|------|-----------| -| `findExecAuto` | Localiza chamadas ExecAuto por rotina ou tabela | -| `findMvcPattern` | Busca padrões MVC por model_id ou tabela | -| `searchByTable` | Cross-search por alias de tabela | -| `searchKnowledge` | Busca padrões, templates e convenções | -| `searchDocuments` | Busca nos documentos PDF de treinamento | +Algumas tools extras (`findExecAuto`, `findMvcPattern`, `searchByTable`, +`searchDocuments`, `listModules`) existem apenas para credenciais de tier interno — +as skills as marcam com "(se disponível no seu tier)". Sem elas, o caminho +equivalente é `ragSearchKnowledge`/`ragSearchDocs`. ## Deploy via TDS-CLI @@ -356,8 +355,9 @@ saveLocal=/patches/ protheus/ ├── .mcp.json # config do MCP (aponta para start.sh) ├── CLAUDE.md # convenções + regra de modelos + Agent Teams -├── skills/ # 18 skills especializadas +├── skills/ # 19 skills especializadas │ ├── init-project/ # setup do projeto +│ ├── arqueologia/ # mapa do legado da fatia │ ├── brainstorm/ # design aprovado │ ├── plan/ # plano de implementação │ ├── implement/ # orquestração Agent Team diff --git a/protheus/hooks/advpl-encoding-pre.sh b/protheus/hooks/advpl-encoding-pre.sh new file mode 100755 index 0000000..a0e6c2f --- /dev/null +++ b/protheus/hooks/advpl-encoding-pre.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# advpl-encoding-pre.sh — bloqueia Edit/Write em fonte CP-1252 ANTES da corrupção +# Ativado por PreToolUse (Write|Edit) +# +# Por quê PRE e não só o advpl-encoding.sh (PostToolUse): quando o Edit lê um .prw +# CP-1252 assumindo UTF-8, os bytes altos viram U+FFFD e o arquivo é regravado já +# corrompido — o hook Post detecta, mas os acentos originais JÁ se perderam. Este +# hook barra a ferramenta antes da leitura destrutiva. O advpl-encoding.sh +# continua como rede de segurança pós-gravação. + +set -euo pipefail + +if ! command -v jq &>/dev/null; then + echo "⚠️ ENCODING(pre): jq não encontrado — verificação ignorada" + exit 0 +fi + +INPUT=$(cat) +FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') + +# Sem caminho, arquivo novo (Write de arquivo inexistente) ou não-ADVPL: não interfere +[[ -z "$FILE" || ! -f "$FILE" ]] && exit 0 +case "$FILE" in + *.prw|*.PRW|*.tlpp|*.TLPP) ;; + *) exit 0 ;; +esac + +command -v python3 &>/dev/null || exit 0 + +# Mesma detecção do advpl-encoding.sh: CP1252 = bytes altos que não decodificam UTF-8 +ENCODING_STATE=$(python3 - "$FILE" <<'PYEOF' +import sys + +filepath = sys.argv[1] +with open(filepath, 'rb') as f: + data = f.read() + +if not data or all(b < 128 for b in data): + print("ASCII") + sys.exit(0) + +if data.startswith(b'\xef\xbb\xbf'): + print("UTF8") + sys.exit(0) + +try: + data.decode('utf-8') + print("UTF8") +except UnicodeDecodeError: + print("CP1252") +PYEOF +) + +if [[ "$ENCODING_STATE" == "CP1252" ]]; then + BASENAME=$(basename "$FILE") + cat >&2 <', '') +open(p, 'w', encoding='cp1252', newline='').write(s) +PY + +Confirme depois com: file "$FILE" (deve reportar ISO-8859). +EOMSG + exit 2 +fi + +exit 0 diff --git a/protheus/hooks/hooks.json b/protheus/hooks/hooks.json index 86b02be..68661a7 100644 --- a/protheus/hooks/hooks.json +++ b/protheus/hooks/hooks.json @@ -12,6 +12,18 @@ ] } ], + "PreToolUse": [ + { + "matcher": "Write|Edit", + "hooks": [ + { + "type": "command", + "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" advpl-encoding-pre.sh", + "timeout": 10 + } + ] + } + ], "PostToolUse": [ { "matcher": "Write|Edit", diff --git a/protheus/hooks/session-context.cjs b/protheus/hooks/session-context.cjs index 60b8fde..edf50fa 100755 --- a/protheus/hooks/session-context.cjs +++ b/protheus/hooks/session-context.cjs @@ -12,13 +12,13 @@ emitSessionContext({ profile: 'external', cleanupTbcDbs: true, groups: [ - { title: 'Ciclo de desenvolvimento (nesta ordem)', names: ['init-project', 'brainstorm', 'plan', 'implement', 'deploy', 'qa', 'verify'] }, + { title: 'Ciclo de desenvolvimento (nesta ordem)', names: ['init-project', 'arqueologia', 'brainstorm', 'plan', 'implement', 'deploy', 'qa', 'verify'] }, { title: 'Geracao e revisao de codigo', names: ['writer', 'reviewer', 'compile', 'mvc-generator', 'tlpp-rest-endpoint-generator', 'query-builder', 'migrate'] }, { title: 'Consulta e diagnostico', names: ['specialist', 'patterns', 'sql', 'data-dictionary-lookup', 'diagnose'] }, { title: 'Testes e relatorios', names: ['test-web', 'smartview-relatorio', 'feedback'] }, ], notes: [ - 'MCP tools disponiveis: searchFunction, findEndpoint, findSmartView, listModules (catalogo) + ragSearchKnowledge, ragSearchDocs (busca semantica) — plugin protheus tbc-knowledge', + 'MCP tools disponiveis: searchFunction, findEndpoint, findSmartView, searchKnowledge, submitFeedback (catalogo) + ragSearchKnowledge, ragSearchDocs (busca semantica) — plugin protheus tbc-knowledge', 'Regra de modelos: opus para brainstorm/design, sonnet para implementacao e review/QA, haiku somente para deploy/compilacao.', ], }); diff --git a/protheus/skills/arqueologia/SKILL.md b/protheus/skills/arqueologia/SKILL.md new file mode 100644 index 0000000..9ea03d8 --- /dev/null +++ b/protheus/skills/arqueologia/SKILL.md @@ -0,0 +1,137 @@ +--- +name: arqueologia +description: Mapeia a fatia do legado do cliente que a demanda atual vai tocar — customizações existentes, Pontos de Entrada, tabelas e campos customizados, regras de negócio embutidas — e grava em docs/legado/ com escala de confiança. Extração parcial e append-only, o mapa cresce por demanda. Use antes do /protheus:brainstorm quando a área da demanda não tiver mapa. +--- + + +Escopo é a fatia que a demanda toca, nunca a base inteira. Se o mapa que você está +prestes a escrever não cabe em uma sessão, o escopo está errado — volte e reduza. +Esta skill NÃO gera código e NÃO modifica fonte nenhum: escreve apenas em `docs/legado/`. + + +Toda afirmação do mapa sai rotulada com a escala do `/protheus:specialist` (seção 5.5): +**CONFIRMADO** (lido no fonte, no SX3 do ambiente ou no retorno do MCP sobre código) · +**INFERIDO** (padrão TOTVS, convenção, dicionário padrão não conferido no cliente) · +**LACUNA** (não sei e não consegui descobrir — precisa do dev, do cliente ou do ambiente). + +## Passo 0 — Escopo e profundidade + +Pergunte ao dev, com `AskUserQuestion`: + +1. **Qual a fatia?** (módulo, rotina, tabela ou processo que a demanda toca) +2. **Qual profundidade?** + - `1` **Essencial** (padrão) — inventário + regras de negócio das customizações da fatia + - `2` **Completo** — inclui dicionário customizado (campos `X_`, índices SIX, + parâmetros `MV_`/`TB_`) e mapa de Pontos de Entrada por rotina + - `3` **Detalhado** — inclui arqueologia de Git por fonte e fluxo por função não-trivial + +Profundidade 3 numa fatia grande estoura a sessão. Se o dev pedir 3, confirme o +tamanho da fatia antes de começar. + +## Passo 0.5 — Fatia já mapeada: conferir antes de acrescentar + +Antes do inventário, olhe a `docs/legado/COBERTURA.md`. Se a fatia **já tem** linha lá, +esta rodada não é extração nova — é **conferência**. Mapa que ninguém confere envelhece +em silêncio, e o `/protheus:brainstorm` trata cada regra CONFIRMADO como restrição do +design: regra CONFIRMADO desatualizada é pior que LACUNA, porque ninguém desconfia dela. + +Para cada `RN--NN` marcada **CONFIRMADO** no `docs/legado/.md`, volte ao +`arquivo:linha` de origem e responda uma das três: + +| Situação no fonte de hoje | O que fazer | +|---|---| +| A regra continua lá, igual | nada — não regrave a linha | +| O `arquivo:linha` mudou, o comportamento não | registre em `## Divergências desta rodada` citando a referência antiga e a nova | +| O comportamento mudou, ou o trecho sumiu | **achado**: `## Divergências desta rodada` com antes, depois e data; a regra antiga vai para "Arquivadas" **com o motivo** | + +Comece pela seção `## Entregas` (o que o `/protheus:verify` devolveu ao mapa no Passo +2.5): entrega registrada ali que não aparece nas regras é onde a divergência está mais +provável. + +Reporte a contagem de divergências no Passo 6, junto com as LACUNAs — é o número que +diz se o mapa desta fatia ainda vale alguma coisa. + +## Passo 1 — Inventário da fatia (CONFIRMADO por construção) + +```bash +find . -name "*.prw" -o -name "*.tlpp" | sort # fontes +grep -rn "User Function" --include="*.prw" --include="*.tlpp" . # entradas +grep -rln "" --include="*.prw" --include="*.tlpp" . # quem toca a tabela da demanda +git log --oneline --follow -- # idade e churn de cada fonte +``` + +Para cada fonte da fatia registre: nome, módulo, tipo (User Function / PE / MVC / +relatório), data do último commit, e se está no MIT043. + +**Divergência MIT043 × disco é achado próprio, não ruído — e não é LACUNA.** Fonte no +disco e ausente do MIT043 é customização que ninguém registrou: o comportamento dela é +CONFIRMADO (basta ler o arquivo); o que falta é **registro**. Liste essas divergências +em seção separada do mapa — é onde mora o comportamento que vai quebrar. + +Inventário longo (base grande, varredura de PEs) roda em **subagente**, em paralelo — +não segure os outros passos esperando. + +## Passo 2 — Pontos de Entrada por rotina + +Para cada rotina TOTVS tocada pela demanda, liste os PEs já customizados no cliente, +o que cada um retorna e o que acontece se retornar `.F.`. Cruze com o MCP — +`searchKnowledge({ keyword: "ponto de entrada " })` e +`searchFunction({ name: "" })` — para saber o que o PE **deveria** fazer +(INFERIDO) versus o que o fonte do cliente **faz** (CONFIRMADO). *(`findEndpoint` +não serve aqui: indexa endpoints REST, não Pontos de Entrada.)* + +Dois PEs no mesmo ponto, ou lógica de negócio dentro do próprio arquivo de PE em vez +de função externa, são achados. + +## Passo 3 — Dicionário customizado (profundidade 2+) + +Campos `X_`/prefixo do cliente nas tabelas da fatia, com **tipo e tamanho reais do +SX3** — não deduzidos do nome. Índices SIX customizados. Parâmetros `MV_`/`TB_` que a +fatia lê. Sem ambiente à mão, use o dicionário padrão +(`https://terminaldeinformacao.com/wp-content/tabelas/.php`, minúsculo) e +marque INFERIDO: o cliente pode ter alterado. + +## Passo 4 — Regras de negócio embutidas + +Do fonte, não da documentação: condicionais com lógica de domínio, validações, +constantes com nome de negócio, mensagens ao usuário, `TODO`/`FIXME`. Numere +`RN--01`, `RN--02`… Cada uma com rótulo de confiança e o `arquivo:linha` +de onde saiu. + +Comentário antigo é **evidência de intenção, não prova de comportamento**: o que o +código faz é CONFIRMADO; o que o comentário diz que ele faz é INFERIDO. + +## Passo 5 — Gravar (append-only) + +`docs/legado/.md`, com o cabeçalho: + +> ⚠️ **Extração parcial.** Cobre apenas ``, gerada em `` para a demanda +> ``. Append-only: rodadas futuras acrescentam, nunca reescrevem. Fora desta +> fatia, o mapa não existe. + +E com estas seções fixas (crie vazias na primeira rodada — os outros passos e skills +escrevem nelas, e seção improvisada quebra o append-only na rodada seguinte): + +- `## Regras` — as `RN--NN` do Passo 4 +- `## Entregas` — preenchida pelo Passo 2.5 do `/protheus:verify` +- `## Divergências desta rodada` — preenchida pelo Passo 0.5 (conferência) +- `## Arquivadas` — regra que deixou de valer, sempre **com motivo e data** + +E `docs/legado/COBERTURA.md`, **uma linha por fatia mapeada** (nunca uma por fonte — +catalogar a base inteira é exatamente o que o HARD-GATE proíbe): + +| Fatia | Fontes cobertos | Demanda | Data | +|---|---|---|---| +| `faturamento-pedido` | `RFATA001.prw`, `PE_MT410TOK.prw` (+6) | TICKET-123 | 2026-08-08 | + +E, no rodapé, a contagem do que **ninguém mapeou ainda** — o dado mais importante do +arquivo (obtida por `find`, atualizada a cada rodada): + +> Fontes fora de qualquer fatia: **1.192** de 1.200. A contagem só diminui quando +> vira cobertura — nunca a reduza sem mapear. + +## Passo 6 — Encerrar + +Reporte: fontes inventariados, regras numeradas, quantas LACUNAs, divergências +MIT043, e a cobertura acumulada. Encaminhe para `/protheus:brainstorm`, que vai +ancorar o design neste mapa. **Não** gere código. diff --git a/protheus/skills/brainstorm/SKILL.md b/protheus/skills/brainstorm/SKILL.md index 4b0e18b..a1d681e 100644 --- a/protheus/skills/brainstorm/SKILL.md +++ b/protheus/skills/brainstorm/SKILL.md @@ -1,6 +1,6 @@ --- name: brainstorm -description: Planejamento de desenvolvimento ADVPL/TLPP — intake de MIT044, explora o projeto, faz perguntas, propõe abordagens e gera design aprovado antes de qualquer código. Encadeia /protheus:plan. +description: Planejamento de desenvolvimento ADVPL/TLPP — intake de MIT044, explora o projeto, pergunta em rodadas com resposta recomendada e gera design aprovado antes de qualquer código. Use ao iniciar qualquer nova feature ou desenvolvimento Protheus. Encadeia /protheus:plan. --- @@ -8,10 +8,10 @@ Não gere nenhum código ADVPL/TLPP, não crie arquivos .prw/.tlpp e não invoqu -Brainstorm é design, e design roda em **opus**. Antes do Passo 0, verifique qual modelo está -atendendo esta sessão. Se **não** for opus, PARE e responda exatamente: +Brainstorm é design, e design roda em **opus**. Antes do Passo 0, verifique +qual modelo está atendendo esta sessão. Se **não** for opus, PARE e responda exatamente: -> ⚠️ O brainstorm exige o modelo **opus**. +> ⚠️ O brainstorm exige o modelo **opus** (regra de modelos deste plugin). > Sessão atual: ``. Rode `/model opus` e chame `/protheus:brainstorm` de novo. Não explore o projeto, não faça as perguntas do Passo 2 e não gere design fora do opus. @@ -60,33 +60,45 @@ git log --oneline -15 2>/dev/null grep -rn "User Function" . --include="*.prw" --include="*.tlpp" | grep -i "^.*PE_\|^.*MT\|^.*FA" | head -20 ``` +Leia também, se existirem: +- `docs/legado/.md` e `docs/legado/COBERTURA.md` — mapa da `/protheus:arqueologia`. + Fatia da demanda fora das fatias mapeadas na COBERTURA e base cheia de customização + não documentada? Ofereça rodar `/protheus:arqueologia` antes de seguir. +- `docs/legado/regressao/*.md` das demandas anteriores na mesma fatia — cada item é + **restrição** do design, não sugestão. + Com base na exploração, identifique: - Próximo sequencial disponível no padrão `R[MOD][TYPE][SEQ]` - Módulos já desenvolvidos neste projeto - Padrão de namespace TLPP, se houver - Pontos de Entrada já customizados (para evitar duplicidade) +> Exploração longa (repositório grande, varredura de PEs) roda em **subagente**, em +> paralelo. Não segure a primeira rodada de perguntas esperando o resultado: só as +> perguntas que dependem dele esperam. + --- ## Passo 1.5 — Consultar base de conhecimento (MCP obrigatório) -Antes de formular perguntas ou propor abordagens, consulte o MCP `tbc-knowledge`: +Consulte o MCP `tbc-knowledge` em dois momentos — as consultas **genéricas** agora, +antes de qualquer pergunta; as **parametrizadas** assim que tiver módulo e tabelas +(do MIT044 do Passo 0, ou das respostas da rodada 1 do Passo 2). Não chute o +parâmetro de uma consulta parametrizada: se módulo/tabela ainda não foram +respondidos, a consulta espera a rodada 1. ``` -# Funções existentes no módulo relevante -searchFunction({ module: "", limit: 20 }) - -# Pontos de Entrada disponíveis para a tabela/rotina -findEndpoint({ keyword: "" }) -findExecAuto({ target: "" }) -findMvcPattern({ table: "" }) - -# Padrões e convenções aplicáveis +# Genéricas — rodam já: searchKnowledge({ skill: "protheus-patterns", keyword: "nomenclatura" }) searchKnowledge({ skill: "protheus-patterns", keyword: "tratamento erros" }) +ragSearchDocs({ query: "" }) -# Material de treinamento relevante -searchDocuments({ keyword: "" }) +# Parametrizadas — rodam quando módulo/tabelas estiverem definidos: +searchFunction({ module: "", limit: 20 }) +searchKnowledge({ keyword: "ponto de entrada " }) # PEs (findEndpoint é REST, não PE) +findExecAuto({ target: "" }) # (se disponível no seu tier — senão use ragSearchKnowledge) +findMvcPattern({ table: "" }) # (se disponível no seu tier — senão use ragSearchKnowledge) +findEndpoint({ keyword: "" }) # só se a demanda envolver API REST ``` Use os resultados para: @@ -94,13 +106,56 @@ Use os resultados para: - Evitar reescrever comportamento já fornecido pelo ERP - Embasar as abordagens propostas no Passo 3 com evidências da Knowledge Base +### Regra — fato é meu, decisão é sua + +**Achar fato é trabalho seu, nunca do dev.** Se a resposta está no repositório, no +MCP `tbc-knowledge`, no dicionário de dados ou no ambiente (existe PE para esta rotina? +qual o próximo sequencial? qual o tipo do campo no SX3?), vá buscar — não pergunte. +Busca cara, despache um subagente (`Agent`). + +**Decisão é do dev.** Trade-off, regra de negócio, prioridade, o que o cliente +aceita — apresente com recomendação e espere a resposta. + +Teste rápido: se duas pessoas com acesso ao mesmo ambiente chegariam à mesma +resposta, é fato — busque. Se depende do que o cliente quer, é decisão — pergunte. + +Subagente rodando é pré-requisito não resolvido, não pausa da entrevista: só as +perguntas que dependem daquele fato esperam o retorno. O resto da fronteira você +pergunta agora, enquanto ele roda. + --- -## Passo 2 — Perguntas (uma por vez) +## Passo 2 — Perguntas (em rodadas, com resposta recomendada) + +Monte a **árvore de decisão** da tarefa e trabalhe por **rodadas**. A **fronteira** é o +conjunto de decisões cujos pré-requisitos já estão resolvidos — as que dá para perguntar +**agora** sem chutar resposta que você ainda não ouviu. + +Pergunte a fronteira **inteira em uma única mensagem** (use `AskUserQuestion` com +múltiplas questões; múltipla escolha sempre que possível). Depois **pare e espere** as +respostas — não avance para o design com pergunta em aberto. Cada resposta empurra a +fronteira: decisões resolvidas destravam as que dependiam delas. Recalcule e faça a +próxima rodada. + +**Regra de dependência:** pergunta cuja resposta depende de outra pergunta ainda +aberta **nesta** rodada pertence à rodada **seguinte** — nunca à atual. + +### Formato de cada pergunta -Faça **uma pergunta por mensagem**. Prefira múltipla escolha quando possível. +Toda pergunta sai com a sua recomendação junto — o dev decide, mas nunca no escuro: -### Sequência recomendada: +> ❓ **P1 — **: +> +> ➡️ **Recomendo:** — +> `[CONFIRMADO | INFERIDO]` · fonte: + +O rótulo segue a escala do `/protheus:specialist` (seção 5.5): CONFIRMADO só com +código ou retorno da KB destilada de código; documentação sozinha é INFERIDO. + +Sem evidência, não recomende: diga o que faltou e volte ao Passo 1.5 para buscar antes +de perguntar. Recomendação sem fonte é chute com aparência de análise. + +### Raiz da árvore — rodada 1 1. **O que você precisa construir?** (descrição livre) 2. **Qual tipo de artefato?** @@ -110,12 +165,39 @@ Faça **uma pergunta por mensagem**. Prefira múltipla escolha quando possível. - `R` Relatório 3. **Qual módulo?** (FAT, FIN, EST, COM, RH…) 4. **Quais tabelas são envolvidas?** (ex: SA1 Clientes, SC5 Pedidos) -5. **Existe algum Ponto de Entrada padrão já disponível para este caso?** - *(se for PE — verificar na documentação TDN ou no código existente)* + +> Itens 3 e 4 só entram na rodada 1 se o MIT044 do Passo 0 não os respondeu. + +**Entre a rodada 1 e a rodada 2**, rode as consultas parametrizadas do Passo 1.5 +com o módulo e as tabelas respondidos. + +### Rodada 2 — depende das respostas e do MCP + +5. **Qual Ponto de Entrada usar?** — *não pergunte se existe PE: o + `searchKnowledge({ keyword: "ponto de entrada " })` acabou de responder.* + Apresente os PEs encontrados, com o que cada um permite, sua recomendação e o + motivo — e peça a escolha. 6. **Precisa persistir dados?** Se sim, em tabela padrão ou customizada? 7. **Há validações ou regras de negócio específicas do cliente?** -Pare quando tiver informações suficientes para propor abordagens. +### Ramos que as respostas abrem (rodadas 3+) + +A raiz não é a árvore inteira. Cada resposta abre decisões que só existiam depois +dela — não deixe passar em silêncio: + +| Resposta da raiz | Decisões que ela abre | +|---|---| +| Tabela customizada | prefixo e faixa no dicionário, campos `X_`, índices SIX, exclusiva ou compartilhada, registro no MIT043 | +| Ponto de Entrada | qual PE exatamente, o que retornar, comportamento em erro (aborta a gravação ou só avisa?), efeito em ExecAuto e dentro de loop | +| MVC completo | Modelo 1 ou 3, grid, validação de linha vs de modelo, momento do commit | +| Relatório | volume esperado, filtros, saída (tela / planilha / SmartView) | +| Persistência em tabela padrão | campos customizados necessários, impacto em rotinas TOTVS que já gravam nela | + +**Quando parar:** a entrevista termina quando a **fronteira está vazia** — todo ramo da +árvore visitado e nada assumido em silêncio. "Já tenho informação suficiente" não é +condição de parada — é a sensação que costuma vir logo antes do retrabalho. Antes de +passar ao Passo 3, liste cada premissa que você está adotando sem ter perguntado; se +essa lista não estiver vazia, a fronteira também não está: volte e pergunte. --- @@ -136,7 +218,8 @@ Sempre indique qual você recomenda e por quê. ## Passo 4 — Apresentar design -Apresente o design em seções, aguardando aprovação após cada uma: +Apresente o design em seções, aprovando em três blocos: (4.1–4.2), (4.3–4.4) e +(4.5–4.6). Aguarde a aprovação de cada bloco antes do seguinte. ### 4.1 — Visão geral - Nome do arquivo: `R[MOD][TYPE][SEQ].prw` (ou `.tlpp`) @@ -154,20 +237,55 @@ Apresente o design em seções, aguardando aprovação após cada uma: - `xFilial()` obrigatório em toda busca ### 4.4 — Tratamento de erros -- `ErrorBlock` + programação defensiva com guard clauses (**BEGIN SEQUENCE PROIBIDO**) +- Programação defensiva com guard clauses, conforme as convenções inegociáveis do + CLAUDE.md do plugin (Try-Catch em TLPP, ErrorBlock só em ADVPL clássico, + **BEGIN SEQUENCE PROIBIDO**) - Mensagens ao usuário ### 4.5 — Checklist de conformidade -- Notação húngara em todas as variáveis? -- Limite de 8 chars no nome da User Function? +- Convenções inegociáveis do CLAUDE.md do plugin (notação húngara, escopos, tratamento de erros)? +- Limite de 8 chars no nome da User Function (`.prw`)? - ProtheusDoc completo? - Registrar no MIT043? +### 4.6 — Premissas e aceites registrados + +Registre aqui os aceites por escrito que o dev deu durante o Passo 2 (premissa +aceita + justificativa). Se ao montar o design surgir premissa **nova** que não +passou pelo Passo 2, ela não entra nesta lista: vira pergunta agora — e a resposta +**invalida os blocos já aprovados que ela sustenta**, que devem ser reapresentados. + +Design aprovado com premissa em aberto não é design aprovado — é retrabalho +agendado, e o implementador vai decidir sozinho o que você não perguntou. + --- ## Passo 5 — Transição para planejamento -Após aprovação do design, salve o design doc em `docs/plans/YYYY-MM-DD-[modulo]-[descricao]-design.md`: +Após aprovação do design, salve o design doc em `docs/plans/YYYY-MM-DD-[modulo]-[descricao]-design.md`. + +Grave também o vínculo em `docs/plans/YYYY-MM-DD-[modulo]-[descricao].gates.json` — o +mesmo arquivo que o `/protheus:implement` usa como estado dos gates, criado uma etapa +antes: + +```json +{ + "slug": "YYYY-MM-DD-[modulo]-[descricao]", + "design": { "status": "aprovado", "doc": "docs/plans/YYYY-MM-DD-[modulo]-[descricao]-design.md" }, + "plan": { "status": "pendente" } +} +``` + +Se já existir `.gates.json` **com este mesmo slug** (re-brainstorm da mesma feature), +não regrave o template: atualize **só** a chave `design` e preserve todas as demais +(`plan`, `spec_review`, `code_review`…) — sobrescrever apagaria os gates de execução já +conquistados. Se o design mudou depois de implementação feita, avise o dev que os +gates gravados podem não valer mais e pergunte se zera. + +Se existir `.gates.json` de **outra** feature em andamento, apenas avise o dev que há +mais de uma feature aberta. + +Anuncie: ``` Design aprovado! @@ -178,12 +296,3 @@ Próximo passo: > O `protheus:plan` irá decompor o design em tasks tipadas para ADVPL > e preparar o plano para os teammates de implementação, revisão, compilação e testes E2E Playwright. - ---- - -## Consulta de Conhecimento - -Se precisar de informação não disponível no MCP, consulte o RAG: -``` -searchKnowledge({ keyword: "" }) -``` diff --git a/protheus/skills/deploy/SKILL.md b/protheus/skills/deploy/SKILL.md index 7574d63..2d699e7 100644 --- a/protheus/skills/deploy/SKILL.md +++ b/protheus/skills/deploy/SKILL.md @@ -8,7 +8,7 @@ Você vai conduzir a compilação e deploy de artefatos ADVPL/TLPP no AppServer ## HARD GATE -- **Leia `docs/plans/.gates.json`** e confirme: `tests_unit.status=ok`, reviews `ok`. O arquivo é a fonte de +- **Leia `docs/plans/.gates.json`** e confirme: reviews `ok`. O arquivo é a fonte de verdade — não confie em afirmação da conversa. Não inicie a compilação se as tarefas de implementação não estiverem concluídas e aprovadas nos reviews. diff --git a/protheus/skills/diagnose/SKILL.md b/protheus/skills/diagnose/SKILL.md index 9636b97..470238f 100644 --- a/protheus/skills/diagnose/SKILL.md +++ b/protheus/skills/diagnose/SKILL.md @@ -29,6 +29,16 @@ Consulte a referência completa via MCP: searchKnowledge({ skill: "protheus-diagnose", keyword: "erros compilacao" }) ``` +**Rotule a causa raiz antes de propor correção** (escala do `/protheus:specialist`: +CONFIRMADO / INFERIDO / LACUNA): + +- **CONFIRMADO** — a mensagem de erro, o log ou o fonte mostram a causa. Pode corrigir. +- **INFERIDO** — a causa é a mais provável pelo padrão do erro, mas o log não prova. + Diga isso ao dev e proponha o teste que confirma **antes** de mexer no código. +- **LACUNA** — falta informação (log truncado, ambiente inacessível, erro não + reproduzido). Peça o que falta. Não proponha correção sobre LACUNA: vira palpite + com aparência de diagnóstico, e o dev passa a tarde testando a hipótese errada. + ### Fase 3 — Propor correção - Explicar a causa raiz com clareza diff --git a/protheus/skills/feedback/SKILL.md b/protheus/skills/feedback/SKILL.md index c46f8df..8bbae60 100644 --- a/protheus/skills/feedback/SKILL.md +++ b/protheus/skills/feedback/SKILL.md @@ -41,6 +41,26 @@ Analisar o contexto da conversa (o que Claude disse de errado, o que o dev corri --- +## Passo 2.5 — Checar duplicata e contradição (antes de mostrar o rascunho) + +A KB não tem supersessão automática — dois feedbacks contraditórios convivem, e quem +busca pode seguir o errado. Antes do Passo 3, busque o tema: + +``` +searchKnowledge({ keyword: "", limit: 5 }) +``` + +Se vier registro próximo, mostre ao dev junto com o rascunho e pergunte: + +> "Encontrei este(s) aprendizado(s) relacionado(s). O seu **complementa**, **corrige** +> ou **duplica** algum deles?" + +- **Corrige** → abra o rascunho com a linha `⚠️ CORRIGE aprendizado de :` + no campo ERRO, para quem buscar depois achar a versão nova junto da velha. +- **Duplica** → não submeta; avise o dev que já existe. + +--- + ## Passo 3 — Dev revisa e aprova Apresentar o rascunho e perguntar: @@ -51,6 +71,20 @@ Aguardar resposta. Aplicar edições se o dev solicitar. Só avançar após apro --- +## Passo 3.5 — Candidato a promoção? (ANTES de submeter — a tag entra no payload) + +Junto da aprovação do rascunho, pergunte: + +> "Esse erro é provável de se repetir com outros devs? Se sim, qual skill deveria +> **impedir** isso (reviewer, writer, patterns, hook de lint...)?" + +Se o dev apontar destino, acrescente `promote:` (ex.: `promote:reviewer`) às +TAGS do rascunho **antes** do Passo 4 — o `submitFeedback` não tem update: tag que +não entra na submissão não existe. É o filtro que a revisão periódica usa para +decidir o que sai da KB e vira regra de skill. + +--- + ## Passo 4 — Submeter via MCP Chamar a tool MCP `submitFeedback` com os campos aprovados: diff --git a/protheus/skills/implement/SKILL.md b/protheus/skills/implement/SKILL.md index 205eeb6..7ecff5a 100644 --- a/protheus/skills/implement/SKILL.md +++ b/protheus/skills/implement/SKILL.md @@ -6,8 +6,26 @@ disable-model-invocation: true ## Instruções para Claude -Leia o plano mais recente em `docs/plans/` (arquivo terminado em `-plan.md`). -Se não houver plano, recomende `/protheus:plan` primeiro. +Leia o plano da feature ativa (ver Passo 0). Se não houver plano, recomende +`/protheus:plan` primeiro. + +--- + +## Passo 0 — Retomar, se houver estado + +Leia `docs/plans/.gates.json` **antes de criar qualquer time**. O estágio vem +do arquivo, nunca da memória da conversa. A varredura de retomada olha **só os +estágios de execução**, nesta ordem: `spec_review` → `code_review` → `lint` → +`deploy` → `qa_e2e` (`design` e `plan` ficam fora — têm vocabulário próprio): + +- Arquivo com `plan.status = "ok"` e sem estágio de execução gravado → comece do + Estágio 0. +- Estágios de execução parciais (ex.: `spec_review.status = "ok"`, `code_review` + ausente) → entre no primeiro estágio de execução cuja chave ainda não está + `"status": "ok"`, e diga ao dev o que já passou e de onde vai continuar. +- Mais de um `.gates.json` com `plan.status = "ok"` e execução incompleta → liste e + pergunte qual retomar. +- Sem `.gates.json` → recomende `/protheus:plan`. --- @@ -36,10 +54,33 @@ Se Agent Teams não estiver habilitado, informe o usuário e caia no fallback (E ## Artefato de estado dos gates (gates.json) -Todo veredito de gate é GRAVADO em `docs/plans/.gates.json` — a skill seguinte LÊ o -arquivo em vez de confiar na memória da conversa. Atualize a chave do estágio ao concluí-lo: -`{ "tests_unit": {...}, "spec_review": "ok", "code_review": "ok", "lint": "ok", "deploy": {...}, "qa_e2e": {...} }`. -Pipeline retomável: sessão nova lê o arquivo e continua de onde parou. +Todo veredito de gate é GRAVADO em `docs/plans/.gates.json` — o **mesmo arquivo +que o `/protheus:brainstorm` criou** ao aprovar o design (o slug é o da feature, sem +sufixo `-plan`). Nunca crie um segundo arquivo. A skill seguinte LÊ o arquivo em vez +de confiar na memória da conversa (doc oficial: "hooks/artefatos são determinísticos; +instruções são consultivas"). Esquema único: + +```json +{ + "slug": "2026-07-12-fat-desconto", + "design": { "status": "aprovado", "doc": "docs/plans/2026-07-12-fat-desconto-design.md" }, + "plan": { "status": "ok", "file": "docs/plans/2026-07-12-fat-desconto-plan.md" }, + "spec_review": { "status": "ok" }, + "code_review": { "status": "ok" }, + "lint": { "status": "ok" }, + "deploy": { "status": "ok", "patch": "patch_20260712.ptm" }, + "qa_e2e": { "status": "ok", "cenarios": 5 } +} +``` + +Regras do esquema: +- Toda chave é **objeto com `status`** — nunca string solta. +- `design` e `plan` têm vocabulário próprio (`aprovado`/`pendente`/`ok`) e ficam + **fora** da varredura de retomada do Passo 0. +- Os estágios de **execução**, na ordem: `spec_review` → `code_review` → `lint` → + `deploy` → `qa_e2e`. Atualize a chave ao concluir cada um. + +Pipeline vira retomável: sessão nova lê o arquivo e continua de onde parou. ## Estágio 0 — Criar Agent Team diff --git a/protheus/skills/mvc-generator/SKILL.md b/protheus/skills/mvc-generator/SKILL.md index 4b87693..adff27c 100644 --- a/protheus/skills/mvc-generator/SKILL.md +++ b/protheus/skills/mvc-generator/SKILL.md @@ -160,6 +160,13 @@ Run through the MVC Generation Checklist below to verify completeness. --- +## MVC in TLPP (.tlpp) — KB learning + +MVC in `.tlpp` requires: declare the `Namespace`, use `user function` (not +`static`), and reference with the **full namespace + `U_`** in `SetMenuDef`, +`FWLoadModel` and button `Action`s — otherwise the buttons do not show up in +FwMBrowse and the browse loads empty. + ## Troubleshooting - **"Field not found in SX3"**: The field referenced in `FWFormStruct` must exist in the data dictionary (SX3). Run `CFGX023()` or use SIGACFG to register missing fields. diff --git a/protheus/skills/patterns/SKILL.md b/protheus/skills/patterns/SKILL.md index c3cf792..39fd6ba 100644 --- a/protheus/skills/patterns/SKILL.md +++ b/protheus/skills/patterns/SKILL.md @@ -62,6 +62,12 @@ searchKnowledge({ skill: "protheus-patterns", keyword: "tratamento erros" }) Padrões de busca com MsSeek, gravação com RecLock, commit e rollback. +- `RecLock`/`MsUnlock` sempre em par e **sempre com alias explícito**: + `->(MsUnlock())`, nunca `MsUnlock()` solto — solto ele destrava a workarea + corrente, que pode não ser a que você travou se o posicionamento mudou no meio. +- Depois de `Posicione()`/`DbSeek()`/`MSSeek()` o alias fica **posicionado**: leia os + demais campos com `ALIAS->CAMPO`. Não repita o `Posicione()` campo a campo. + Consulte a referência completa via MCP: ``` searchKnowledge({ skill: "protheus-patterns", keyword: "banco dados" }) @@ -84,6 +90,11 @@ searchKnowledge({ skill: "protheus-patterns", keyword: "dicionario dados" }) Regra de unicidade: 1 PE por arquivo. Padrão MVC e padrão legado com exemplos. +**Momento certo do PE.** Validação **bloqueante** vai em PE de validação +(`MT100TOK`, `MODELPOS`/`FORMPOS`/`FORMLINEPOS`), que roda ANTES da gravação e cujo +retorno `.F.` aborta. PE **pós-gravação** (`MT103FIN`/`MT103FIM`, `MODELCOMMIT*`) não +bloqueia nada: retornar `.F.` ali é ignorado e a gravação já aconteceu. + Consulte a referência completa via MCP: ``` searchKnowledge({ skill: "protheus-patterns", keyword: "pontos entrada" }) diff --git a/protheus/skills/plan/SKILL.md b/protheus/skills/plan/SKILL.md index 5ff1d2e..d5c86e2 100644 --- a/protheus/skills/plan/SKILL.md +++ b/protheus/skills/plan/SKILL.md @@ -6,18 +6,32 @@ disable-model-invocation: true ## Instruções para Claude -Leia o design doc mais recente em `docs/plans/` antes de começar. -Se não houver design doc, recomende `/protheus:brainstorm` primeiro. +Derive a feature ativa dos `docs/plans/*.gates.json` — do arquivo, nunca da memória +da conversa. Se não houver `.gates.json` nem design doc, recomende +`/protheus:brainstorm` primeiro. --- ## Passo 1 — Ler o design aprovado -```bash -ls -t docs/plans/*.md | head -3 -``` +Liste os `docs/plans/*.gates.json` e derive o estágio de cada feature **do arquivo**: + +| Estado observado no `.gates.json` | Estágio | Próximo passo | +|---|---|---| +| `design.status != "aprovado"` | design em aberto | volte ao `/protheus:brainstorm` | +| `design` aprovado, `plan.status = "pendente"` | pronto para planejar | siga este skill | +| `plan.status = "ok"`, gates de execução ausentes | plano pronto | `/protheus:implement` | +| gates de execução parciais | implementação em andamento | `/protheus:implement` (retoma) | + +Se houver **mais de uma** feature com `design` aprovado e `plan` pendente, liste-as +numeradas com data e slug e **pergunte qual planejar**. Nunca escolha a mais recente +por conta própria: o dev pode estar voltando a uma feature da semana passada, e +planejar a errada só aparece no review — depois de o implementer já ter escrito código. + +Design doc antigo sem `.gates.json` (anterior a esta versão): confirme com o dev qual +arquivo usar antes de seguir. -Leia o design doc identificado. Extraia: +Leia o design doc da feature escolhida. Extraia: - Lista de artefatos a implementar (nome do arquivo, tipo, responsabilidade) - Módulo Protheus (FAT, FIN, EST, COM, RH…) - Tabelas envolvidas @@ -118,6 +132,75 @@ Bloqueio: compilação bem-sucedida (RPO atualizado) --- +## Passo 3.5 — Regressão: o que não pode quebrar + +Toda customização Protheus mexe em terreno compartilhado: um PE roda dentro de rotina +TOTVS que outras customizações também usam; um campo `X_` novo entra em tabela que a +rotina padrão grava; um ExecAuto muda o que rotinas a jusante leem. + +### Alcance medido — o que o plano não previu + +Rode esta medição **antes de escrever o arquivo de regressão** — se a resposta for +REDESENHA, nenhum arquivo órfão fica para trás. Varra os callers e **confronte a +varredura com a lista fechada de fontes do Passo 2**, separando o que ela atinge +fora dela. + +Para cada função, PE ou campo que a demanda altera: + +```bash +grep -rn "U_\|\|" --include="*.prw" --include="*.tlpp" . +``` + +Referência que cai em fonte **fora da lista do plano** é alcance não previsto. Antes de +salvar o plano, apresente ao dev e espere resposta: + +> Alcance medido de ****: +> - Fontes no plano: `` +> - Atingidos fora do plano: `` (ou "nenhum") +> +> 1. **SEGUE** — cada atingido vira item na tabela de regressão abaixo +> 2. **REDESENHA** — o alcance mostra que a demanda é maior que o desenhado; volta ao +> `/protheus:brainstorm` + +Se a varredura não for possível (o caller está em fonte padrão TOTVS que não está no +repo), diga isso com todas as letras: "alcance não medido" é informação. Silêncio vira +"não tem impacto", que é a frase que costuma preceder o incidente. + +Antes de salvar o plano, escreva `docs/legado/regressao/.md` — um item por +comportamento que **existia antes** e precisa continuar existindo depois. + +Fonte dos itens, nesta ordem: +1. Regras CONFIRMADO de `docs/legado/.md` (se o mapa da `/protheus:arqueologia` + existir) que a demanda toca de raspão +2. Comportamento de PE que outras rotinas dependem +3. Campo de tabela padrão que outra rotina TOTVS também grava +4. Retorno de função com caller fora da demanda (`grep -rn "U_"`) + +| ID | Origem (`arquivo:linha` ou `RN--NN`) | O que precisa continuar verdadeiro | Como verificar | Sinal de violação | +|---|---|---|---|---| +| W001 | `RFATA001.prw:210` (`RN-FAT-03`) | Pedido sem transportadora continua gravando com frete zero | cenário E2E `W001` no plano de QA (`/protheus:qa` → `/protheus:test-web`) | pedido sem transportadora passa a bloquear a gravação | + +Regras: +- **Só entra item CONFIRMADO.** Comportamento INFERIDO ou LACUNA vai para uma seção + "Observações", sem peso de regressão — vigiar o que você não confirmou produz alarme + falso, e alarme falso mata o arquivo em duas demandas. +- **IDs são estáveis e append-only.** Item que deixou de valer não é apagado: vai para + a seção "Arquivadas" **com o motivo e a data** — o motivo é o que impede a próxima + demanda de reintroduzir o problema que esta resolveu. +- **Todo item verificável vira cenário E2E no plano de QA** — o `W001` entra no escopo + da task de testes E2E do Passo 3, nomeado pelo ID, e é lá que ele é exercido. Item + que só dá para conferir lendo o fonte entra como **inspeção nomeada** (`arquivo:linha` + a conferir no `/protheus:verify`). Item sem forma de verificar é observação, não item + de regressão. + +Esta lista cobre só o que **existia antes**. O comportamento que esta demanda +**criar** entra na mesma lista no Passo 2.5 do `/protheus:verify`, depois do E2E. + +Na demanda seguinte que tocar a mesma fatia, o `/protheus:brainstorm` lê este arquivo +no Passo 1 e cada item vira **restrição** do design — não sugestão. + +--- + ## Passo 4 — Salvar o plano Salve o plano completo em: @@ -126,6 +209,9 @@ Salve o plano completo em: docs/plans/YYYY-MM-DD-[modulo]-[descricao]-plan.md ``` +E atualize o `.gates.json` da feature: +`"plan": { "status": "ok", "file": "docs/plans/-plan.md" }` + Formato do plano: ```markdown @@ -134,6 +220,7 @@ Formato do plano: **Design:** docs/plans/[design-doc].md **Módulo:** [MOD] **Data:** YYYY-MM-DD +**Regressão:** docs/legado/regressao/[slug].md (ou "não se aplica — justificativa") ## Tasks de Implementação @@ -174,3 +261,10 @@ Se precisar de informação não disponível no MCP, consulte o RAG: ``` searchKnowledge({ keyword: "" }) ``` + +## Rastreabilidade task → verificação → evidência + +- Numere as tasks com ID estável (`T1`, `T2`, …) no plano. +- Cada cenário E2E referencia o ID da task ou do item de regressão que exercita + (`T1: …`, `W001: …`), para o `/protheus:verify` conseguir dar veredito item a item. +- Evidências E2E ficam em `evidencias//`. diff --git a/protheus/skills/qa/SKILL.md b/protheus/skills/qa/SKILL.md index 6f5c462..2d069cf 100644 --- a/protheus/skills/qa/SKILL.md +++ b/protheus/skills/qa/SKILL.md @@ -10,7 +10,7 @@ Você vai conduzir testes E2E e análise de qualidade contra os artefatos compil ## HARD GATE -- **Leia `docs/plans/.gates.json`** e confirme: `deploy.status=ok` e `tests_unit.status=ok`. O arquivo é a fonte de +- **Leia `docs/plans/.gates.json`** e confirme: `deploy.status=ok`. O arquivo é a fonte de verdade — não confie em afirmação da conversa. Não inicie testes se: diff --git a/protheus/skills/query-builder/SKILL.md b/protheus/skills/query-builder/SKILL.md index 3336b14..4896a19 100644 --- a/protheus/skills/query-builder/SKILL.md +++ b/protheus/skills/query-builder/SKILL.md @@ -172,6 +172,13 @@ WHERE SA1.D_E_L_E_T_ = ' ' --- +## Dialect pitfalls (from the KB) + +- `ORDER BY A, B DESC` applies `DESC` **only to B** — repeat the direction on + each column (`A DESC, B DESC`) when everything must be descending. +- Subquery alias **without** `AS` (`FROM (SELECT ...) SUB`) — Oracle rejects + `AS` in that position; without it the query works on both Oracle and MSSQL. + ## SQL Injection Prevention **Never concatenate user input directly into SQL strings.** Use `FWExecStatement` to parameterize all dynamic values. diff --git a/protheus/skills/reviewer/SKILL.md b/protheus/skills/reviewer/SKILL.md index b218c3d..f154bfa 100644 --- a/protheus/skills/reviewer/SKILL.md +++ b/protheus/skills/reviewer/SKILL.md @@ -55,6 +55,19 @@ Verifique (e exija do `writer`/`migrate`) os dois passos de [`references/validac --- +## Falsos positivos conhecidos (aprendizados da KB — NÃO reportar) + +- **`.tlpp` com `Local x as `**: o runtime JÁ inicializa (numeric→0, + character→"", logical→.F., date→31/12/1899). "Variável não inicializada" ali é + falso CRÍTICO — a exigência de inicialização explícita vale para `.prw` sem + tipagem. +- Ao mesmo tempo, **cobre**: parâmetro/variável tipado comparado com `NIL` + (`var != NIL` em `as Date`/`as Character` gera `Incompatible types` na + compilação — o certo é `Empty(var)`). O `advpls appre` NÃO detecta erro de + tipo: **lint limpo não garante compilação**. + +--- + ## Consulta de Conhecimento Se precisar de informação não disponível no MCP, consulte o RAG: diff --git a/protheus/skills/specialist/SKILL.md b/protheus/skills/specialist/SKILL.md index 572dd15..5af6590 100644 --- a/protheus/skills/specialist/SKILL.md +++ b/protheus/skills/specialist/SKILL.md @@ -44,19 +44,19 @@ Use as tools do MCP `tbc-knowledge`: `findSmartView({ keyword: "", team: "SIGAXXX" })` **Para ExecAuto:** -`findExecAuto({ target: "" })` +`findExecAuto({ target: "" })` — (se disponível no seu tier — senão use `ragSearchKnowledge`) **Para MVC:** -`findMvcPattern({ model_id: "", table: "" })` +`findMvcPattern({ model_id: "", table: "" })` — (se disponível no seu tier — senão use `ragSearchKnowledge`) **Para busca por tabela (cross-search):** -`searchByTable({ table: "" })` +`searchByTable({ table: "" })` — (se disponível no seu tier — senão use `ragSearchKnowledge`) **Para funções específicas:** `searchFunction({ name: "", module: "" })` **Para listar módulos:** -`listModules()` +`listModules()` — (se disponível no seu tier — senão use `searchFunction` por módulo) ### 3. Consulte os Padrões e Convenções @@ -76,15 +76,42 @@ searchKnowledge({ keyword: "" }) ### 5. Consulte Material de Treinamento -`searchDocuments({ keyword: "" })` +`ragSearchDocs({ query: "" })` + +### 5.5. Classifique a confiança de cada afirmação + +Toda afirmação técnica que você levar para a análise sai com um rótulo e a fonte: + +| Rótulo | Quando usar | Fonte que sustenta | +|---|---|---| +| **CONFIRMADO** | o comportamento está no código do ERP destilado na KB, ou você leu o fonte do projeto | retorno do MCP com assinatura/rotina + arquivo:linha do projeto | +| **INFERIDO** | o padrão é consistente com o que a KB e a doc mostram, mas nada afirma este caso | TDN, `ragSearchDocs`, analogia com rotina parecida | +| **LACUNA** | depende do ambiente do cliente, de parâmetro ou de dado que você não tem | nada — é pergunta para o dev ou consulta ao ambiente | + +**Teto por proveniência.** A KB protheus tem conhecimento destilado de código-fonte +do ERP: resposta sobre assinatura, ExecAuto ou padrão MVC pode chegar a **CONFIRMADO**. +Conhecimento que vem só de documentação (TDN, docs processadas) tem teto **INFERIDO** — +documentação descreve a intenção; só o código prova o comportamento. + +**Dicionário de dados:** `terminaldeinformacao.com` e a KB entregam o dicionário +**padrão** — é INFERIDO até conferir no SX3 do ambiente do cliente, porque +customização de dicionário é a regra, não a exceção. + +Regras: +- Sem fonte, **não escreva a linha**. Omitir é honesto; preencher por dedução é o que + faz o dev descobrir em produção que o campo era `C` e não `N`. +- Nunca promova INFERIDO a CONFIRMADO sem ter ido buscar. "Provavelmente é assim" + continua INFERIDO. +- Na dúvida, o rótulo mais baixo. Uma LACUNA honesta custa uma pergunta; um + CONFIRMADO errado custa o retrabalho inteiro. ### 6. Apresente Análise + Recomendação -Antes de gerar código, apresente: +Antes de gerar código, apresente (cada afirmação com o rótulo da seção 5.5): 1. O que encontrou na Knowledge Base 2. O que encontrou no TDN 3. Abordagem recomendada -4. Riscos/Considerações +4. Riscos/Considerações — LACUNAs listadas explicitamente ### 7. Gere o Código diff --git a/protheus/skills/verify/SKILL.md b/protheus/skills/verify/SKILL.md index 77ca6a0..7af47ad 100644 --- a/protheus/skills/verify/SKILL.md +++ b/protheus/skills/verify/SKILL.md @@ -8,8 +8,8 @@ Você vai conduzir a verificação final antes de liberar os artefatos para prod ## HARD GATE -- **Leia `docs/plans/.gates.json`** e confirme: todas as chaves `ok`. O arquivo é a fonte de - verdade — não confie em afirmação da conversa. +- **Leia `docs/plans/.gates.json`** e confirme: todas as chaves `ok` (reviews, lint, deploy, qa_e2e). Não confie em + afirmação da conversa — o arquivo é a fonte de verdade (pipeline retomável). Não inicie a verificação se: - QA não foi concluído com sucesso @@ -42,6 +42,18 @@ Verifique cada item obrigatório: - [ ] Commits com mensagens descritivas - [ ] PR criado (se aplicável) +### 1.6 — Regressão do legado +- [ ] O cabeçalho do plano tem a linha `**Regressão:**` — apontando para o arquivo + **ou** com justificativa explícita de "não se aplica". Cabeçalho sem a linha = + Passo 3.5 do plan foi pulado → **bloqueia** (não é "não se aplica") +- [ ] O arquivo `docs/legado/regressao/.md` referenciado existe e **cada item + tem veredito registrado**: verificado / não verificado / quebrou +- [ ] Itens com cenário E2E: verde no `.gates.json` (`qa_e2e.status = "ok"`), com o + cenário nomeado pelo ID do item nas evidências +- [ ] Itens verificados por inspeção: `arquivo:linha` conferido no fonte final +- [ ] Item que deixou de valer foi para "Arquivadas" com motivo — não apagado +- [ ] Item sem veredito **bloqueia o verify** + ## Passo 2 — Confirmar com o usuário Use `AskUserQuestion`: @@ -56,11 +68,64 @@ Itens pendentes: [listar se houver] Confirma liberação para produção? ``` +## Passo 2.5 — Writeback: devolver a entrega ao mapa do legado + +O `docs/legado/.md` só cresce **antes** da demanda, pela `/protheus:arqueologia`. +Se nada for devolvido depois do ship, o mapa envelhece no instante em que o patch sai: +a próxima demanda na mesma fatia lê um retrato do legado que esta demanda já mudou — e +o `/protheus:brainstorm` ancora o design nele. Confirmada a liberação (Passo 2), faça +os três registros abaixo. **Nada aqui bloqueia — bloquear é papel do 1.6.** Este passo +é o que paga a próxima demanda. + +### 2.5.1 — Itens novos em `docs/legado/regressao/.md` (append-only, mesma numeração `W`) + +O Passo 3.5 do `/protheus:plan` escreveu o que **existia antes**. Agora, com o código +compilado e o E2E verde, escreva o que **passou a existir**: + +1. **Comportamento que esta entrega estabeleceu** e que outra demanda pode desfazer sem + perceber. Só entra o que tem forma de verificar (cenário E2E do `/protheus:qa` ou + `arquivo:linha` no fonte final) e só CONFIRMADO — o resto vai para "Observações". +2. **Item da lista original que a entrega provou errado** vai para "Arquivadas" **com o + motivo e a data** — nunca apagado, nunca corrigido no lugar. Item invalidado por + feedback do dev/cliente durante a homologação conta aqui: o motivo é o que impede a + próxima demanda de reintroduzir o problema. +3. **Item que aponta para fora deste repositório** (robô/RPA do cliente, integração + Fluig, job agendado) entra com o repositório ou sistema no campo Origem. O ciclo + não roda lá — o item é o que avisa. + +### 2.5.2 — Registro de entrega em `docs/legado/.md` + +Acrescente uma linha à seção `## Entregas` (crie a seção se não existir; não reescreva +nada do que já está lá — vale o append-only do Passo 5 da `/protheus:arqueologia`): + +| Data | Demanda | Fontes criados/alterados | PEs afetados | RN novas ou alteradas | Regressão | +|---|---|---|---|---|---| +| 2026-08-08 | TICKET-123 (``) | `RFATA001.prw` (novo) | `MT410TOK` | `RN-FAT-07` (nova — `RFATA001.prw:88`) | `docs/legado/regressao/.md` | + +- **Só o que está no fonte final entra** — a linha sai do artefato compilado no patch, + não do design doc. Design é intenção; a fatia registra o que ficou no RPO. +- Regra de negócio que a demanda **criou ou mudou** entra numerada (`RN--NN`, + continuando a sequência do arquivo) com `arquivo:linha` — rótulo CONFIRMADO por + construção: você acabou de ler o fonte liberado. +- Fatia sem mapa: crie o arquivo só com o cabeçalho de extração parcial e a seção + `## Entregas`. Registro de entrega **não é arqueologia** — não saia inventariando. + +### 2.5.3 — `docs/legado/COBERTURA.md` + +Acrescente o ticket desta entrega à coluna `Demanda` da fatia tocada. + +> Entrega que não volta pro mapa é conhecimento que morre no patch. + ## Passo 3 — Orientar distribuição ``` ✅ VERIFICAÇÃO CONCLUÍDA — [nome da demanda] +Mapa do legado atualizado (Passo 2.5): +- docs/legado/[fatia].md — Entregas: +1 · RN novas: [lista ou "nenhuma"] +- docs/legado/regressao/[slug].md — itens novos: [N] · arquivados: [N] +(se o 2.5 foi pulado, diga "writeback NÃO feito" — omissão visível, não silêncio) + Artefatos aprovados: - [listar artefatos com tipo] diff --git a/protheus/skills/writer/SKILL.md b/protheus/skills/writer/SKILL.md index 7ada57a..f4ec541 100644 --- a/protheus/skills/writer/SKILL.md +++ b/protheus/skills/writer/SKILL.md @@ -5,7 +5,7 @@ description: Gera código ADVPL/TLPP para Protheus seguindo obrigatoriamente: no ## Guardrails anti-alucinação (OBRIGATÓRIO) -- **Antes de gerar:** *Validação de Símbolos da API* — toda função/classe/método/namespace deve existir na doc (TDN), no MCP (`searchFunction`/`searchByTable`) ou em `references`. Nunca inferir símbolo de memória (causa #1 de `Cannot find method`/`Class not found`). +- **Antes de gerar:** *Validação de Símbolos da API* — toda função/classe/método/namespace deve existir na doc (TDN), no MCP (`searchFunction`/`ragSearchDocs`) ou em `references`. Nunca inferir símbolo de memória (causa #1 de `Cannot find method`/`Class not found`). - **Depois de gerar:** *Verificação de Completude* — gap analysis item a item; nada omitido em silêncio. - Refs: [`../reviewer/references/validacao-simbolos-e-completude.md`](../reviewer/references/validacao-simbolos-e-completude.md) · qualidade G1–G5: [`../reviewer/references/sonarqube-rules-reference.md`](../reviewer/references/sonarqube-rules-reference.md). @@ -42,8 +42,8 @@ searchKnowledge({ skill: "protheus-patterns", keyword: "notacao hungara" }) # Verificar se já existe função/PE padrão para o caso searchFunction({ name: "", module: "" }) findEndpoint({ keyword: "" }) -findExecAuto({ target: "" }) -findMvcPattern({ table: "" }) +findExecAuto({ target: "" }) # (se disponível no seu tier — senão use ragSearchKnowledge) +findMvcPattern({ table: "" }) # (se disponível no seu tier — senão use ragSearchKnowledge) ``` **Ordem de prioridade das fontes:** @@ -69,6 +69,15 @@ Antes de gerar qualquer codigo, pergunte: --- +## Regras de campo (aprendizados da KB) + +- **Nunca** abrir `FWMsgRun`/`MsgRun`/`MSDialog` dentro do `VALID`/`bValid` de um + campo — o painel disputa foco com o VALID pendente e a tela trava (deadlock de + foco). Processamento longo sai do VALID. +- Parâmetro/variável **tipado** (`as Date`, `as Character`…): testar com + `Empty(var)` — `var != NIL` gera `Incompatible types`. E o `advpls appre` não + pega erro de tipo: lint limpo não garante compilação. + ## Base de Conhecimento (MCP) Use as tools do MCP `tbc-knowledge`: diff --git a/tests/hooks/advpl-encoding-pre.test.sh b/tests/hooks/advpl-encoding-pre.test.sh new file mode 100755 index 0000000..3f0395f --- /dev/null +++ b/tests/hooks/advpl-encoding-pre.test.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# Testes do advpl-encoding-pre.sh (PreToolUse — bloqueia Edit/Write em CP-1252) +set -uo pipefail + +HOOK="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/protheus/hooks/advpl-encoding-pre.sh" +TMPDIR=$(mktemp -d); trap 'rm -rf "$TMPDIR"' EXIT +FAIL=0 + +run_hook() { # $1 = file path + echo "{\"tool_input\":{\"file_path\":\"$1\"}}" | bash "$HOOK" 2>"$TMPDIR/err" +} + +echo "T1 — .prw CP-1252 com acentos bloqueia (exit 2, instrução Python)" +printf 'Local cMsg := "Valida\xe7\xe3o"\n' > "$TMPDIR/RFAT.prw" # ç/ã em CP-1252 +run_hook "$TMPDIR/RFAT.prw"; RC=$? +if [[ $RC -eq 2 ]] && grep -q "cp1252" "$TMPDIR/err"; then echo " ✅ block com instrução"; else echo " ❌ RC=$RC"; FAIL=1; fi + +echo "T2 — .prw UTF-8 passa (o Post cuida da conversão)" +printf 'Local cMsg := "Validação"\n' > "$TMPDIR/RUTF.prw" +run_hook "$TMPDIR/RUTF.prw"; RC=$? +[[ $RC -eq 0 ]] && echo " ✅ passa" || { echo " ❌ RC=$RC"; FAIL=1; } + +echo "T3 — .prw ASCII puro passa" +printf 'Local nQtd := 0\n' > "$TMPDIR/RASC.prw" +run_hook "$TMPDIR/RASC.prw"; RC=$? +[[ $RC -eq 0 ]] && echo " ✅ passa" || { echo " ❌ RC=$RC"; FAIL=1; } + +echo "T4 — arquivo novo (inexistente) passa" +run_hook "$TMPDIR/NOVO.prw"; RC=$? +[[ $RC -eq 0 ]] && echo " ✅ passa" || { echo " ❌ RC=$RC"; FAIL=1; } + +echo "T5 — extensão não-ADVPL passa mesmo em CP-1252" +printf '\xe7\xe3o\n' > "$TMPDIR/nota.txt" +run_hook "$TMPDIR/nota.txt"; RC=$? +[[ $RC -eq 0 ]] && echo " ✅ passa" || { echo " ❌ RC=$RC"; FAIL=1; } + +[[ $FAIL -eq 0 ]] && echo "TODOS OS TESTES PASSARAM" || { echo "FALHAS"; exit 1; } diff --git a/tests/run-all.sh b/tests/run-all.sh index 8660c70..d04de40 100755 --- a/tests/run-all.sh +++ b/tests/run-all.sh @@ -6,6 +6,7 @@ REPO="$(cd "$(dirname "$0")/.." && pwd)" FAIL=0 run() { echo; echo "━━ $1"; shift; "$@" || FAIL=1; } +run "hooks: advpl-encoding-pre (bloqueio)" "$REPO/tests/hooks/advpl-encoding-pre.test.sh" run "hooks: advpl-lint" "$REPO/tests/hooks/advpl-lint.test.sh" run "hooks: fluig-lint" "$REPO/tests/hooks/fluig-lint.test.sh" run "hooks: sonar-engine (regras EngPro)" node --test "$REPO/tests/hooks/sonar-engine.test.cjs"