wegho-agentes 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/.agents/AGENT_WORKFLOW.md +528 -0
  2. package/.agents/AI_COMPATIBILITY.md +332 -0
  3. package/.agents/CLI.md +222 -0
  4. package/.agents/README.md +130 -0
  5. package/.agents/cli.js +389 -0
  6. package/.agents/code-auditor-agent.ts +333 -0
  7. package/.agents/config.ts +145 -0
  8. package/.agents/context-loader.ts +300 -0
  9. package/.agents/core/agent-parallelizer.test.ts +94 -0
  10. package/.agents/core/agent-parallelizer.ts +108 -0
  11. package/.agents/core/architecture-agent.ts +237 -0
  12. package/.agents/core/base-agent.ts +311 -0
  13. package/.agents/core/cache-manager.test.ts +147 -0
  14. package/.agents/core/cache-manager.ts +184 -0
  15. package/.agents/core/documentation-agent.ts +183 -0
  16. package/.agents/core/feedback-collector.ts +207 -0
  17. package/.agents/core/frontend-agent.ts +210 -0
  18. package/.agents/core/inventory-agent.ts +582 -0
  19. package/.agents/core/memory-system.ts +397 -0
  20. package/.agents/core/quality-agent.ts +268 -0
  21. package/.agents/core/retry-utility.test.ts +165 -0
  22. package/.agents/core/retry-utility.ts +140 -0
  23. package/.agents/core/security-agent.ts +217 -0
  24. package/.agents/core/workflow-validator.test.ts +171 -0
  25. package/.agents/core/workflow-validator.ts +158 -0
  26. package/.agents/domains/README.md +53 -0
  27. package/.agents/domains/logistics/route-agent.ts +177 -0
  28. package/.agents/domains/news/cms-agent.ts +158 -0
  29. package/.agents/domains/news/seo-agent.ts +170 -0
  30. package/.agents/domains/production/production-control-agent.ts +169 -0
  31. package/.agents/example-learning-system.js +118 -0
  32. package/.agents/init.ts +164 -0
  33. package/.agents/memory/architecture-agent/failures.json +1 -0
  34. package/.agents/memory/architecture-agent/learnings.json +1 -0
  35. package/.agents/memory/architecture-agent/specialty.md +31 -0
  36. package/.agents/memory/architecture-agent/successes.json +16 -0
  37. package/.agents/memory/cms-agent/failures.json +1 -0
  38. package/.agents/memory/cms-agent/learnings.json +1 -0
  39. package/.agents/memory/cms-agent/specialty.md +30 -0
  40. package/.agents/memory/cms-agent/successes.json +16 -0
  41. package/.agents/memory/documentation-agent/failures.json +1 -0
  42. package/.agents/memory/documentation-agent/learnings.json +1 -0
  43. package/.agents/memory/documentation-agent/specialty.md +33 -0
  44. package/.agents/memory/documentation-agent/successes.json +16 -0
  45. package/.agents/memory/frontend-agent/failures.json +1 -0
  46. package/.agents/memory/frontend-agent/learnings.json +1 -0
  47. package/.agents/memory/frontend-agent/specialty.md +30 -0
  48. package/.agents/memory/frontend-agent/successes.json +16 -0
  49. package/.agents/memory/inventory-agent/failures.json +1 -0
  50. package/.agents/memory/inventory-agent/inventory/index.json +8 -0
  51. package/.agents/memory/inventory-agent/inventory/types.json +77716 -0
  52. package/.agents/memory/inventory-agent/inventory/variables.json +405 -0
  53. package/.agents/memory/inventory-agent/learnings.json +1 -0
  54. package/.agents/memory/inventory-agent/specialty.md +129 -0
  55. package/.agents/memory/inventory-agent/successes.json +30 -0
  56. package/.agents/memory/production-control-agent/failures.json +1 -0
  57. package/.agents/memory/production-control-agent/learnings.json +1 -0
  58. package/.agents/memory/production-control-agent/specialty.md +29 -0
  59. package/.agents/memory/production-control-agent/successes.json +16 -0
  60. package/.agents/memory/quality-agent/failures.json +16 -0
  61. package/.agents/memory/quality-agent/learnings.json +1 -0
  62. package/.agents/memory/quality-agent/specialty.md +31 -0
  63. package/.agents/memory/quality-agent/successes.json +1 -0
  64. package/.agents/memory/reference-repositories.json +271 -0
  65. package/.agents/memory/route-agent/failures.json +1 -0
  66. package/.agents/memory/route-agent/learnings.json +1 -0
  67. package/.agents/memory/route-agent/specialty.md +29 -0
  68. package/.agents/memory/route-agent/successes.json +16 -0
  69. package/.agents/memory/security-agent/failures.json +1 -0
  70. package/.agents/memory/security-agent/learnings.json +1 -0
  71. package/.agents/memory/security-agent/specialty.md +31 -0
  72. package/.agents/memory/security-agent/successes.json +16 -0
  73. package/.agents/memory/seo-agent/failures.json +1 -0
  74. package/.agents/memory/seo-agent/learnings.json +1 -0
  75. package/.agents/memory/seo-agent/specialty.md +31 -0
  76. package/.agents/memory/seo-agent/successes.json +16 -0
  77. package/.agents/orchestrator.ts +438 -0
  78. package/.agents/project-discovery-agent.ts +342 -0
  79. package/.agents/security/pentesting-agent.py +387 -0
  80. package/.agents/security/python-bridge.ts +193 -0
  81. package/.agents/security/vulnerability-db.json +201 -0
  82. package/.agents/task-analyzer-agent.ts +346 -0
  83. package/.agents/test-init-context.js +67 -0
  84. package/INSTALL.md +300 -0
  85. package/LICENSE +21 -0
  86. package/README.md +315 -0
  87. package/docs/AGENT_RULES.md +292 -0
  88. package/docs/BUILD_HISTORY.md +65 -0
  89. package/docs/DESIGN_SYSTEM.md +256 -0
  90. package/docs/LEARNING_SYSTEM.md +326 -0
  91. package/docs/SYMBOLS_TREE.md +182 -0
  92. package/docs/VERSION.md +6 -0
  93. package/docs/architecture.md +111 -0
  94. package/package.json +60 -0
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Code Auditor Agent
3
+ *
4
+ * Responsabilidades:
5
+ * - Escanear código existente em projetos que ainda não têm sistema de agentes
6
+ * - Detectar violações das regras absolutas
7
+ * - Gerar relatório completo com priorização (P0/P1/P2)
8
+ * - Sugerir correções específicas
9
+ */
10
+
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import { validateFileLines } from './config';
14
+
15
+ export interface CodeViolation {
16
+ file: string;
17
+ line?: number;
18
+ type: string;
19
+ severity: 'P0' | 'P1' | 'P2';
20
+ message: string;
21
+ suggestion: string;
22
+ }
23
+
24
+ export interface AuditReport {
25
+ totalFiles: number;
26
+ totalViolations: number;
27
+ p0Count: number;
28
+ p1Count: number;
29
+ p2Count: number;
30
+ violations: CodeViolation[];
31
+ summary: string;
32
+ }
33
+
34
+ export class CodeAuditorAgent {
35
+ private projectRoot: string;
36
+
37
+ constructor(projectRoot: string = process.cwd()) {
38
+ this.projectRoot = projectRoot;
39
+ }
40
+
41
+ /**
42
+ * Encontra todos os arquivos do projeto para auditoria
43
+ */
44
+ private findProjectFiles(): string[] {
45
+ const files: string[] = [];
46
+ const extensions = ['.ts', '.tsx', '.js', '.jsx'];
47
+ const excludeDirs = ['node_modules', '.next', 'dist', 'build', '.git', '.agents'];
48
+
49
+ const walkDir = (dir: string) => {
50
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
51
+
52
+ for (const entry of entries) {
53
+ const fullPath = path.join(dir, entry.name);
54
+
55
+ if (entry.isDirectory()) {
56
+ if (!excludeDirs.includes(entry.name)) {
57
+ walkDir(fullPath);
58
+ }
59
+ } else if (entry.isFile()) {
60
+ const ext = path.extname(entry.name);
61
+ if (extensions.includes(ext)) {
62
+ files.push(fullPath);
63
+ }
64
+ }
65
+ }
66
+ };
67
+
68
+ try {
69
+ walkDir(this.projectRoot);
70
+ } catch (error) {
71
+ console.error('Erro ao escanear diretórios:', error);
72
+ }
73
+
74
+ return files;
75
+ }
76
+
77
+ /**
78
+ * Audita um arquivo individual
79
+ */
80
+ private auditFile(filePath: string): CodeViolation[] {
81
+ const violations: CodeViolation[] = [];
82
+
83
+ if (!fs.existsSync(filePath)) {
84
+ return violations;
85
+ }
86
+
87
+ const content = fs.readFileSync(filePath, 'utf-8');
88
+ const lines = content.split('\n');
89
+ const relPath = path.relative(this.projectRoot, filePath);
90
+
91
+ // Violação 1: Arquivo > 500 linhas (P0)
92
+ const lineCheck = validateFileLines(filePath, 500);
93
+ if (!lineCheck.valid) {
94
+ violations.push({
95
+ file: relPath,
96
+ type: 'file-too-long',
97
+ severity: 'P0',
98
+ message: `Arquivo tem ${lineCheck.lineCount} linhas (limite: 500)`,
99
+ suggestion: 'Refatorar: extrair hooks, componentes filhos ou funções para utils/lib',
100
+ });
101
+ }
102
+
103
+ // Violação 2: Uso de 'any' não justificado (P1)
104
+ lines.forEach((line, index) => {
105
+ if (line.match(/:\s*any(?!\w)/) && !line.includes('// justified') && !line.includes('TODO')) {
106
+ violations.push({
107
+ file: relPath,
108
+ line: index + 1,
109
+ type: 'typescript-any',
110
+ severity: 'P1',
111
+ message: 'Uso de "any" detectado sem justificativa',
112
+ suggestion: 'Usar tipo específico ou "unknown" + type guard',
113
+ });
114
+ }
115
+ });
116
+
117
+ // Violação 3: dangerouslySetInnerHTML sem sanitização (P0)
118
+ if (content.includes('dangerouslySetInnerHTML') && !content.includes('DOMPurify')) {
119
+ violations.push({
120
+ file: relPath,
121
+ type: 'xss-vulnerability',
122
+ severity: 'P0',
123
+ message: 'dangerouslySetInnerHTML sem sanitização detectado',
124
+ suggestion: 'Usar DOMPurify.sanitize() antes de renderizar HTML',
125
+ });
126
+ }
127
+
128
+ // Violação 4: service_role no cliente (P0)
129
+ if (content.match(/service_role|SUPABASE_SERVICE_ROLE/i) && !filePath.includes('server')) {
130
+ violations.push({
131
+ file: relPath,
132
+ type: 'security-critical',
133
+ severity: 'P0',
134
+ message: 'service_role key no código cliente (NUNCA expor no browser!)',
135
+ suggestion: 'Mover para variável de ambiente server-side ou usar anon key',
136
+ });
137
+ }
138
+
139
+ // Violação 5: console.log com dados sensíveis (P0)
140
+ lines.forEach((line, index) => {
141
+ if (line.match(/console\.(log|debug|info).*?(password|token|secret|key|credential)/i)) {
142
+ violations.push({
143
+ file: relPath,
144
+ line: index + 1,
145
+ type: 'security-leak',
146
+ severity: 'P0',
147
+ message: 'console.log com dados sensíveis detectado',
148
+ suggestion: 'Remover log ou usar técnica de mascaramento',
149
+ });
150
+ }
151
+ });
152
+
153
+ // Violação 6: Inputs sem validação (P1)
154
+ if (content.includes('<input') && !content.match(/zod|yup|validator/i)) {
155
+ violations.push({
156
+ file: relPath,
157
+ type: 'missing-validation',
158
+ severity: 'P1',
159
+ message: 'Inputs detectados sem validação (Zod/Yup)',
160
+ suggestion: 'Adicionar schema de validação com Zod ou Yup',
161
+ });
162
+ }
163
+
164
+ // Violação 7: fetch() sem tratamento de erro (P1)
165
+ lines.forEach((line, index) => {
166
+ if (line.includes('fetch(') || line.includes('axios.')) {
167
+ const nextLines = lines.slice(index, index + 10).join('\n');
168
+ if (!nextLines.match(/\.catch|try|error/i)) {
169
+ violations.push({
170
+ file: relPath,
171
+ line: index + 1,
172
+ type: 'missing-error-handling',
173
+ severity: 'P1',
174
+ message: 'fetch() ou axios sem tratamento de erro',
175
+ suggestion: 'Adicionar .catch() ou try-catch',
176
+ });
177
+ }
178
+ }
179
+ });
180
+
181
+ // Violação 8: Componente com lógica de API direta (P2)
182
+ if (relPath.includes('components/') && !relPath.includes('pages/')) {
183
+ if (content.match(/fetch\(|axios\.|supabase\./)) {
184
+ violations.push({
185
+ file: relPath,
186
+ type: 'architecture-violation',
187
+ severity: 'P2',
188
+ message: 'Componente com chamada de API direta',
189
+ suggestion: 'Extrair lógica para hook customizado ou service',
190
+ });
191
+ }
192
+ }
193
+
194
+ // Violação 9: NEXT_PUBLIC_ com dados sensíveis (P0)
195
+ if (content.match(/NEXT_PUBLIC_.*?(SECRET|KEY|PASSWORD|TOKEN)/i)) {
196
+ violations.push({
197
+ file: relPath,
198
+ type: 'security-critical',
199
+ severity: 'P0',
200
+ message: 'Variável sensível exposta com NEXT_PUBLIC_',
201
+ suggestion: 'Remover NEXT_PUBLIC_ e usar apenas no server-side',
202
+ });
203
+ }
204
+
205
+ return violations;
206
+ }
207
+
208
+ /**
209
+ * Executa auditoria completa do projeto
210
+ */
211
+ async auditProject(): Promise<AuditReport> {
212
+ console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
213
+ console.log('🔍 AUDITORIA DE CÓDIGO EXISTENTE');
214
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
215
+
216
+ console.log('📂 Escaneando arquivos do projeto...');
217
+ const files = this.findProjectFiles();
218
+ console.log(`✅ ${files.length} arquivos encontrados\n`);
219
+
220
+ console.log('🔍 Analisando código...');
221
+ const allViolations: CodeViolation[] = [];
222
+
223
+ for (const file of files) {
224
+ const violations = this.auditFile(file);
225
+ allViolations.push(...violations);
226
+ }
227
+
228
+ console.log(`✅ Análise concluída\n`);
229
+
230
+ // Classificar por severidade
231
+ const p0Violations = allViolations.filter(v => v.severity === 'P0');
232
+ const p1Violations = allViolations.filter(v => v.severity === 'P1');
233
+ const p2Violations = allViolations.filter(v => v.severity === 'P2');
234
+
235
+ // Gerar relatório
236
+ const report: AuditReport = {
237
+ totalFiles: files.length,
238
+ totalViolations: allViolations.length,
239
+ p0Count: p0Violations.length,
240
+ p1Count: p1Violations.length,
241
+ p2Count: p2Violations.length,
242
+ violations: allViolations,
243
+ summary: this.generateSummary(allViolations, files.length),
244
+ };
245
+
246
+ return report;
247
+ }
248
+
249
+ /**
250
+ * Gera resumo da auditoria
251
+ */
252
+ private generateSummary(violations: CodeViolation[], totalFiles: number): string {
253
+ let summary = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
254
+ summary += '📊 RELATÓRIO DE AUDITORIA\n';
255
+ summary += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
256
+
257
+ summary += `📁 Arquivos analisados: ${totalFiles}\n`;
258
+ summary += `⚠️ Total de violações: ${violations.length}\n\n`;
259
+
260
+ const p0 = violations.filter(v => v.severity === 'P0');
261
+ const p1 = violations.filter(v => v.severity === 'P1');
262
+ const p2 = violations.filter(v => v.severity === 'P2');
263
+
264
+ summary += `💀 P0 (CRÍTICO): ${p0.length}\n`;
265
+ summary += `⚠️ P1 (IMPORTANTE): ${p1.length}\n`;
266
+ summary += `💡 P2 (MELHORIA): ${p2.length}\n\n`;
267
+
268
+ // Agrupar por tipo
269
+ const byType: Record<string, number> = {};
270
+ violations.forEach(v => {
271
+ byType[v.type] = (byType[v.type] || 0) + 1;
272
+ });
273
+
274
+ summary += '📋 Violações por tipo:\n';
275
+ Object.entries(byType)
276
+ .sort((a, b) => b[1] - a[1])
277
+ .forEach(([type, count]) => {
278
+ summary += ` - ${type}: ${count}\n`;
279
+ });
280
+
281
+ summary += '\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
282
+
283
+ if (p0.length > 0) {
284
+ summary += '\n💀 P0 - BLOQUEADORES CRÍTICOS:\n\n';
285
+ p0.forEach((v, index) => {
286
+ summary += `${index + 1}. ${v.file}${v.line ? `:${v.line}` : ''}\n`;
287
+ summary += ` ❌ ${v.message}\n`;
288
+ summary += ` 💡 ${v.suggestion}\n\n`;
289
+ });
290
+ }
291
+
292
+ if (p1.length > 0 && p1.length <= 10) {
293
+ summary += '\n⚠️ P1 - IMPORTANTES (primeiros 10):\n\n';
294
+ p1.slice(0, 10).forEach((v, index) => {
295
+ summary += `${index + 1}. ${v.file}${v.line ? `:${v.line}` : ''}\n`;
296
+ summary += ` ⚠️ ${v.message}\n`;
297
+ summary += ` 💡 ${v.suggestion}\n\n`;
298
+ });
299
+ }
300
+
301
+ summary += '\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
302
+ summary += '✅ PRÓXIMOS PASSOS:\n';
303
+ summary += '1. Corrigir todas as violações P0 (bloqueadores críticos)\n';
304
+ summary += '2. Revisar violações P1 (importantes para qualidade)\n';
305
+ summary += '3. Considerar violações P2 (melhorias opcionais)\n';
306
+ summary += '4. Execute novamente após correções para validar\n';
307
+ summary += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
308
+
309
+ return summary;
310
+ }
311
+
312
+ /**
313
+ * Salva relatório em arquivo
314
+ */
315
+ saveReport(report: AuditReport): void {
316
+ const reportPath = 'docs/AUDIT_REPORT.md';
317
+
318
+ let content = `# Relatório de Auditoria de Código\n\n`;
319
+ content += `**Data**: ${new Date().toISOString().split('T')[0]}\n`;
320
+ content += `**Arquivos analisados**: ${report.totalFiles}\n`;
321
+ content += `**Total de violações**: ${report.totalViolations}\n\n`;
322
+
323
+ content += `## Resumo\n\n`;
324
+ content += `- 💀 P0 (Crítico): ${report.p0Count}\n`;
325
+ content += `- ⚠️ P1 (Importante): ${report.p1Count}\n`;
326
+ content += `- 💡 P2 (Melhoria): ${report.p2Count}\n\n`;
327
+
328
+ content += report.summary;
329
+
330
+ fs.writeFileSync(reportPath, content, 'utf-8');
331
+ console.log(`✅ Relatório salvo em: ${reportPath}\n`);
332
+ }
333
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Configurações Globais do Sistema de Agentes
3
+ */
4
+
5
+ export type DomainType = 'news' | 'production' | 'logistics' | 'generic';
6
+
7
+ export interface AgentConfig {
8
+ domain: DomainType;
9
+ enabledAgents: string[];
10
+ autoDocumentation: boolean;
11
+ buildTracking: boolean;
12
+ maxFileLines: number;
13
+
14
+ // Memory System Configuration
15
+ memoryEnabled: boolean;
16
+ memoryPath: string;
17
+ feedbackEnabled: boolean;
18
+ autoLearn: boolean; // Aprender automaticamente ou requerer aprovação
19
+ maxMemoryEntries: number; // Limite de entradas na memória
20
+ }
21
+
22
+ export interface DomainConfig {
23
+ name: DomainType;
24
+ agents: string[];
25
+ description?: string;
26
+ }
27
+
28
+ export interface BuildInfo {
29
+ number: number;
30
+ version: string;
31
+ timestamp: string;
32
+ description: string;
33
+ }
34
+
35
+ // Configuração padrão
36
+ export const DEFAULT_CONFIG: AgentConfig = {
37
+ domain: 'generic',
38
+ enabledAgents: ['frontend', 'security', 'documentation', 'architecture', 'quality'],
39
+ autoDocumentation: true,
40
+ buildTracking: true,
41
+ maxFileLines: 500,
42
+
43
+ // Memory System defaults
44
+ memoryEnabled: true,
45
+ memoryPath: '.agents/memory',
46
+ feedbackEnabled: true,
47
+ autoLearn: false, // Padrão: requerer aprovação
48
+ maxMemoryEntries: 1000,
49
+ };
50
+
51
+ // Caminhos importantes
52
+ export const PATHS = {
53
+ docs: 'docs',
54
+ builds: 'docs/builds',
55
+ agents: '.agents',
56
+ agentsCore: '.agents/core',
57
+ agentsDomains: '.agents/domains',
58
+ designSystem: 'docs/DESIGN_SYSTEM.md',
59
+ symbolsTree: 'docs/SYMBOLS_TREE.md',
60
+ buildHistory: 'docs/BUILD_HISTORY.md',
61
+ agentRules: 'docs/AGENT_RULES.md',
62
+ } as const;
63
+
64
+ // Número da build atual (será incrementado automaticamente)
65
+ let currentBuildNumber = 1;
66
+
67
+ export function getCurrentBuildNumber(): number {
68
+ return currentBuildNumber;
69
+ }
70
+
71
+ export function incrementBuildNumber(): number {
72
+ currentBuildNumber++;
73
+ return currentBuildNumber;
74
+ }
75
+
76
+ /**
77
+ * Detecta o domínio do projeto baseado em package.json ou estrutura
78
+ */
79
+ export function detectDomain(): DomainConfig {
80
+ // Tentativa 1: Ler package.json
81
+ try {
82
+ const packageJson = require('../../package.json');
83
+ const projectName = packageJson.name?.toLowerCase() || '';
84
+
85
+ if (projectName.includes('news') || projectName.includes('noticia')) {
86
+ return {
87
+ name: 'news',
88
+ agents: ['cms', 'seo', 'content', 'analytics'],
89
+ description: 'Site de Notícias',
90
+ };
91
+ }
92
+
93
+ if (projectName.includes('production') || projectName.includes('producao') || projectName.includes('minera')) {
94
+ return {
95
+ name: 'production',
96
+ agents: ['production-control', 'quality-control', 'shipping', 'inventory'],
97
+ description: 'Sistema de Produção e Expedição',
98
+ };
99
+ }
100
+
101
+ if (projectName.includes('logistics') || projectName.includes('logistica')) {
102
+ return {
103
+ name: 'logistics',
104
+ agents: ['route', 'fleet', 'warehouse', 'tracking'],
105
+ description: 'Sistema de Logística',
106
+ };
107
+ }
108
+ } catch (error) {
109
+ console.warn('Não foi possível ler package.json para detecção de domínio');
110
+ }
111
+
112
+ // Default: apenas agentes core
113
+ return {
114
+ name: 'generic',
115
+ agents: [],
116
+ description: 'Projeto Genérico',
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Valida se um arquivo excede o limite de linhas
122
+ */
123
+ export function validateFileLines(filePath: string, maxLines: number = 500): {
124
+ valid: boolean;
125
+ lineCount: number;
126
+ message?: string;
127
+ } {
128
+ const fs = require('fs');
129
+ try {
130
+ const content = fs.readFileSync(filePath, 'utf-8');
131
+ const lineCount = content.split('\n').length;
132
+
133
+ if (lineCount > maxLines) {
134
+ return {
135
+ valid: false,
136
+ lineCount,
137
+ message: `⚠️ BLOQUEADO: ${filePath} tem ${lineCount} linhas (limite: ${maxLines})`,
138
+ };
139
+ }
140
+
141
+ return { valid: true, lineCount };
142
+ } catch (error) {
143
+ return { valid: false, lineCount: 0, message: `Erro ao ler arquivo: ${filePath}` };
144
+ }
145
+ }