From protheus-toolkit
Agente de Teste de Mesa para ADVPL/TLPP — análise estática de execução simulada com rigor de engenharia aeroespacial. Use este skill SEMPRE que o usuário pedir para analisar, revisar, rastrear, simular, ou "testar de mesa" uma função ADVPL ou TLPP. Também ative quando o usuário perguntar "o que essa função faz", "tem algum bug aqui", "o retorno está certo", "rastreia essa função", "analisa essa rotina", "simula a execução" ou qualquer variação. Aplica rastreamento linha a linha de variáveis, fluxo de controle, chamadas de função, retornos, e identifica falhas silenciosas, condições não cobertas, e desvios de lógica — tudo sem executar o código, como os engenheiros da NASA nos anos 60-70.
How this skill is triggered — by the user, by Claude, or both
Slash command
/protheus-toolkit:teste-de-mesaThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Nos anos 60 e 70, engenheiros da NASA faziam "desk testing" porque não havia margem para erro:
Nos anos 60 e 70, engenheiros da NASA faziam "desk testing" porque não havia margem para erro: cada linha de código era rastreada manualmente, como se o engenheiro fosse o processador. O resultado era software tão verificado que o foguete voava na primeira tentativa.
Este skill aplica a mesma metodologia a funções ADVPL/TLPP — rastreamento linha a linha, simulando o estado completo da memória, fluxo de controle, e efeitos colaterais, sem precisar subir ambiente Protheus.
Execute todas as fases em ordem. Nunca pule uma fase.
Antes de rastrear qualquer linha, monte o perfil da função:
ASSINATURA
Nome da função / User Function / Method
Parâmetros: nome, tipo esperado, posição
Valor de retorno: tipo esperado, condições
CONTEXTO
Tipo: User Function | Static Function | Method (TLPP Class)
Módulo Protheus provável (Faturamento, PCP, Fiscal, etc.)
Entry point? (PE_xxx, A460xxx, etc.)
Chamada via ExecBlock / MsExecAuto?
Se a função recebe parâmetros sem tipo declarado, infira o tipo mais provável com base
no nome e uso interno. Registre como [INFERIDO].
Rastreie cada variável declarada, em ordem de aparição:
| Variável | Escopo | Tipo Inicial | Linha |
|---|---|---|---|
| cVar | Local | Character "" | 5 |
| nVal | Local | Numeric 0 | 6 |
Escopos ADVPL:
Local — visível apenas na função atualPrivate — visível na função + funções chamadas por ela (PERIGOSO — registre)Static — persiste entre chamadas (MUITO PERIGOSO — registre com ⚠️)Public — global (EXTREMAMENTE PERIGOSO — registre com 🚨)Regras de tipo padrão ADVPL (sem declaração explícita):
Private implícita com valor Nil — registre como 🚨 UNDECLAREDEsta é a fase central. Para cada linha de código:
Mantenha uma tabela de estado atualizada a cada atribuição:
[L.05] cAlias := GetNextAlias()
ESTADO: cAlias = "ZZA001" [SIMULADO — GetNextAlias() retorna alias único]
RISCO: nenhum nesta linha
[L.06] DbUseArea(.T., "TOPCONN", RetSqlName("SB1"), cAlias, .F., .T.)
⚠️ PADRÃO PROIBIDO: DbUseArea+TOPCONN — deveria usar MpSysOpenQuery()
ESTADO: cAlias aberto? INCERTO sem retorno verificado
RISCO: ALTO — sem verificar se área abriu com sucesso
Rastreie cada ramificação com estado explícito:
IF condição
RAMO VERDADEIRO: [rastreie aqui]
Variáveis afetadas: [liste]
ELSE
RAMO FALSO: [rastreie aqui]
Variáveis afetadas: [liste]
ENDIF
⚠️ Condições não cobertas: [identifique Nil, tipo errado, etc.]
Para DO CASE, rastreie cada CASE + OTHERWISE (ou ausência de OTHERWISE = 🚨).
Para FOR/NEXT e WHILE/ENDDO: simule 0 iterações, 1 iteração, N iterações.
REGRA FUNDAMENTAL: Quando o rastreamento encontrar uma chamada a uma funcao/metodo do projeto (nao nativa do Protheus), voce DEVE abrir o codigo-fonte dessa funcao e executar o teste de mesa completo DENTRO dela antes de continuar. Voce esta emulando a execucao real — um processador nao "pula" funcoes, ele entra nelas.
Protocolo de entrada em sub-funcao:
Cache de Funcoes Analisadas:
Mantenha um cache interno durante a analise. Funcoes ja rastreadas nao precisam ser re-analisadas — use o resultado cacheado:
CACHE DE FUNCOES ANALISADAS
┌─────────────────────────┬──────────┬─────────────────────────────────┐
│ Funcao │ Retorno │ Efeitos / Riscos │
├─────────────────────────┼──────────┼─────────────────────────────────┤
│ GravarSI() │ Nil/.T. │ Cria SW0+SW1, lRet nao inic. │
│ GravaPO() │ Nil/.T. │ Cria SW2+SW3, xFilial errado │
│ DeletePurchaseOrder() │ Nil/.T. │ Tem propria Transaction! │
└─────────────────────────┴──────────┴─────────────────────────────────┘
Quando encontrar a mesma funcao novamente:
CHAMADA [CACHE HIT]: lRet := GravarSI(oJson, @cNum, @cErr)
→ Ja analisada. Retorno: Nil (sucesso) ou .T. (erro)
→ Riscos conhecidos: lRet nao inicializada, RecLock sem check
→ Efeitos: cria registros SW0 e SW1
O que NAO entrar (usar valores simulados da tabela de funcoes comuns):
Excepcoes para nao-recursao:
CHAMADA: cRet := FuncaoExterna(param1, param2)
ACAO: [ENTRAR | CACHE HIT | SIMULAR (nativa/framework)]
Parâmetros enviados: [tipo e valor simulado]
Retorno concreto: [valor exato retornado, nao "provavel"]
Efeitos colaterais confirmados: [tabelas alteradas, Private modificadas]
Riscos propagados: [riscos da sub-funcao que afetam o chamador]
Regra de profundidade: Nao existe limite de profundidade. Se a funcao A chama B que chama C que chama D, voce entra em todas. A unica excecao e o cache — se D ja foi analisada quando voce analisou B, use o cache quando encontrar D novamente em C.
Rastreie todos os caminhos de retorno possíveis:
CAMINHO 1: linha X → retorno via Return lValor
Condição de chegada: [qual condição leva aqui]
Valor retornado: [tipo + valor simulado]
Variáveis limpas antes? [áreas fechadas, strings limpas, etc.]
CAMINHO 2: linha Y → retorno via Return .F.
...
CAMINHO AUSENTE? Função pode terminar sem Return explícito?
→ Em ADVPL, terminar sem Return retorna Nil — 🚨 BUG SILENCIOSO
Aplique o checklist completo:
Emita um relatório estruturado:
╔══════════════════════════════════════════════════════╗
║ TESTE DE MESA — RELATÓRIO FINAL ║
╠══════════════════════════════════════════════════════╣
║ Função: [nome] ║
║ Linhas analisadas: [N] ║
║ Caminhos de retorno: [N] ║
╠══════════════════════════════════════════════════════╣
║ SEVERIDADE GERAL: 🔴 CRÍTICO / 🟡 ATENÇÃO / 🟢 OK ║
╠══════════════════════════════════════════════════════╣
║ PROBLEMAS ENCONTRADOS ║
║ 🚨 [críticos — vão causar erro em produção] ║
║ ⚠️ [atenção — podem causar erro em condições X] ║
║ ℹ️ [melhorias — não são bugs mas são riscos] ║
╠══════════════════════════════════════════════════════╣
║ EXECUÇÃO SIMULADA ║
║ Cenário feliz: [descreva o fluxo normal] ║
║ Cenário de falha: [o que acontece quando X falha] ║
╠══════════════════════════════════════════════════════╣
║ RECOMENDAÇÕES ║
║ [lista priorizada de correções] ║
╚══════════════════════════════════════════════════════╝
| Padrão Proibido | Padrão Correto |
|---|---|
DbUseArea(.T.,"TOPCONN",...) | MpSysOpenQuery(cQuery, cAlias) |
TCQuery cSql | MpSysOpenQuery(cQuery, cAlias) |
BeginSQL ... EndSQL | MpSysOpenQuery(cQuery, cAlias) |
| Nome de tabela direto na SQL | RetSqlName("SB1") |
Alias hardcoded "SB1" | GetNextAlias() |
Query sem xFilial() | xFilial("SB1") na condição WHERE |
Query sem D_E_L_E_T_ | AND D_E_L_E_T_ = ' ' |
DtoC(dData) em SQL | DtoS(dData) em SQL |
| DbCloseArea ausente | (cAlias)->(DbCloseArea()) ao fim |
| Tipo | Prefixo | Valor Nil Padrão | Operações Seguras |
|---|---|---|---|
| Character | c | "" | +, SubStr, Len, Upper |
| Numeric | n | 0 | +, -, *, / |
| Logical | l | .F. | .AND., .OR., .NOT. |
| Date | d | CToD("") | +, -, DToS |
| Array | a | {} | AAdd, Len, aArr[n] |
| Object | o | Nil | :method(), :prop |
| Nil | - | Nil | NENHUMA — causa crash |
Quando encontrar essas funções, use os valores simulados abaixo:
| Função | Retorno Simulado |
|---|---|
GetNextAlias() | "AAA001" (único, Character) |
RetSqlName("SB1") | "SB1990" (Character) |
xFilial("SB1") | "01 " (Character, 2 chars) |
GetMV("MV_XXXX") | "" ou valor padrão do parâmetro |
FunName() | Character com nome da função atual |
cUserName | "ADMIN" |
dDataBase | Date() simulada |
cEmpAnt | "01" |
cFilAnt | "01 " |
MpSysOpenQuery(cQ, cA) | lRet = .T. se SQL válida |
RecLock(cAlias, .T.) | .T. (sucesso) |
cAlias = "AAA001", não cAlias = <valor>).Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub guipegoraro/protheus-toolkit --plugin protheus-toolkit