agent-master-devsecops 3.9.0 → 5.1.0

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 (82) hide show
  1. package/README.md +205 -371
  2. package/agents/AGENT_DEVSECOPS.md +32 -417
  3. package/agents/AGENT_INFRA.md +31 -0
  4. package/agents/AGENT_ORCHESTRATOR.md +39 -264
  5. package/agents/AGENT_QA.md +58 -186
  6. package/agents/AGENT_SCRUM.md +23 -190
  7. package/agents/AGENT_SRE.md +22 -173
  8. package/agents/AGENT_UIUX.md +26 -162
  9. package/docs/ARCHITECTURE.md +152 -148
  10. package/docs/CALCULATIONS.md +17 -17
  11. package/docs/CHANGELOG.md +112 -49
  12. package/docs/ENGINEERING_RULES.md +56 -252
  13. package/docs/IDEAS.md +17 -17
  14. package/docs/LOCAL_BACKLOG.md +20 -0
  15. package/docs/STATE.md +111 -43
  16. package/docs/playbooks/PLAYBOOK_CIRCUIT_BREAKER_LLM.md +58 -58
  17. package/docs/playbooks/PLAYBOOK_OPENTELEMETRY_TRACING.md +58 -58
  18. package/package.json +59 -47
  19. package/scripts/auditors/a11y_auditor.js +462 -0
  20. package/scripts/auditors/code_quality_auditor.js +444 -0
  21. package/scripts/auditors/contract_test_validator.js +396 -0
  22. package/scripts/auditors/eval_harness.js +213 -0
  23. package/scripts/auditors/git_hygiene_linter.js +391 -0
  24. package/scripts/auditors/pr_reviewer.js +627 -0
  25. package/scripts/auditors/sast_scanner.js +442 -0
  26. package/scripts/auditors/sca_dependency_auditor.js +673 -0
  27. package/scripts/{bootstrap_cli.js → bin/bootstrap_cli.js} +597 -468
  28. package/scripts/bin/domain_idea_miner.js +658 -0
  29. package/scripts/bin/smart_onboarding.js +905 -0
  30. package/scripts/{web_inspector.js → bin/web_inspector.js} +578 -355
  31. package/scripts/core/architecture_advisor.js +378 -0
  32. package/scripts/core/ast_skeletonizer.js +413 -0
  33. package/scripts/core/autonomous_remediation_engine.js +305 -0
  34. package/scripts/{circuit_breaker.js → core/circuit_breaker.js} +546 -330
  35. package/scripts/core/context_compressor.js +237 -0
  36. package/scripts/core/fast_feature_scaffold.js +840 -0
  37. package/scripts/core/hot_state_cache.js +238 -0
  38. package/scripts/core/knowledge_gateway.js +888 -0
  39. package/scripts/{magic_prompt_generator.js → core/magic_prompt_generator.js} +250 -205
  40. package/scripts/{multi_agent_orchestrator.js → core/multi_agent_orchestrator.js} +421 -258
  41. package/scripts/{otel_tracer.js → core/otel_tracer.js} +335 -228
  42. package/scripts/{perf_benchmark.js → core/perf_benchmark.js} +212 -153
  43. package/scripts/core/sarif_engine.js +299 -0
  44. package/scripts/{sre_remediation_engine.js → core/sre_remediation_engine.js} +236 -174
  45. package/scripts/{universal_packager.js → core/universal_packager.js} +357 -313
  46. package/scripts/integrations/atlassian_client.js +600 -0
  47. package/scripts/integrations/atlassian_sync_action.js +576 -0
  48. package/scripts/integrations/confluence_sync.js +684 -0
  49. package/scripts/integrations/credentials_guard.js +500 -0
  50. package/scripts/integrations/jira_manager.js +722 -0
  51. package/scripts/mcp/handlers/atlassian_handlers.js +300 -0
  52. package/scripts/mcp/handlers/core_handlers.js +419 -0
  53. package/scripts/mcp/handlers/qa_handlers.js +502 -0
  54. package/scripts/mcp/handlers/rules_handlers.js +379 -0
  55. package/scripts/mcp/handlers/scaffold_handlers.js +334 -0
  56. package/scripts/mcp/handlers/sre_handlers.js +443 -0
  57. package/scripts/mcp/resources_registry.js +453 -0
  58. package/scripts/mcp/server.js +408 -0
  59. package/scripts/mcp/tool_handlers.js +444 -0
  60. package/scripts/mcp/tools_registry.js +1123 -0
  61. package/scripts/mcp_server.js +236 -1884
  62. package/.cursorignore +0 -23
  63. package/agents/compact/AGENT_ORCHESTRATOR_COMPACTO.md +0 -53
  64. package/scripts/a11y_auditor.js +0 -187
  65. package/scripts/ast_skeletonizer.js +0 -220
  66. package/scripts/atlassian_client.js +0 -238
  67. package/scripts/atlassian_sync_action.js +0 -269
  68. package/scripts/code_quality_auditor.js +0 -142
  69. package/scripts/confluence_sync.js +0 -337
  70. package/scripts/context_compressor.js +0 -139
  71. package/scripts/contract_test_validator.js +0 -166
  72. package/scripts/credentials_guard.js +0 -216
  73. package/scripts/domain_idea_miner.js +0 -364
  74. package/scripts/eval_harness.js +0 -100
  75. package/scripts/fast_feature_scaffold.js +0 -338
  76. package/scripts/git_hygiene_linter.js +0 -186
  77. package/scripts/hot_state_cache.js +0 -95
  78. package/scripts/jira_manager.js +0 -408
  79. package/scripts/pr_reviewer.js +0 -373
  80. package/scripts/sast_scanner.js +0 -180
  81. package/scripts/sca_dependency_auditor.js +0 -167
  82. package/scripts/smart_onboarding.js +0 -610
package/.cursorignore DELETED
@@ -1,23 +0,0 @@
1
- # .cursorignore - Blindagem de Contexto e Redução de Tokens para Agentes de IA
2
- # Impede a indexação vetorial (RAG) de arquivos utilitários, testes internos e documentação estática,
3
- # reduzindo custos em até ~35.000 tokens por sessão sem apagar nenhum arquivo físico.
4
-
5
- # 1. Suíte de Testes Unitários (Executados via Node.js, não precisam poluir contexto da LLM)
6
- test/
7
- *.test.js
8
-
9
- # 2. Artefatos de Build e Bookmarklets de Browser
10
- dist/
11
- dist/**
12
- *.html
13
-
14
- # 3. Baselines de Benchmark Numérico
15
- benchmarks/
16
- *.baseline.json
17
-
18
- # 4. Manuais Manuais de Instalação para Humanos (A IA não deve indexar)
19
- docs/RULES 16.4 SETUP.md
20
-
21
- # 5. Scripts de Shell e PowerShell Auxiliares
22
- scripts/*.ps1
23
- scripts/*.sh
@@ -1,53 +0,0 @@
1
- === AGENT ORCHESTRATOR & SUÍTE MULTI-AGENTE (LOCAL HIGH-DENSITY EDITION v3.6) ===
2
- [DIRETIVA SUPREMA]: Você é o AGENT ORCHESTRATOR da Suíte Multi-Agente (Orchestrator, UI/UX, DevSecOps, QA, Scrum e SRE). Atue como Arquiteto Staff, Engenheiro Prescritivo, Especialista em Segurança e Auditor Cético.
3
- [COMPATIBILIDADE]: Otimizado para modelos locais (Ollama, vLLM, LM Studio) e nuvem. Siga rigorosamente sem desvios.
4
- [MANDATO PRESCRITIVO]: Proibido encerrar com perguntas passivas ("o que deseja fazer?"). Declare o feito e prescreva o próximo passo já engatilhado.
5
-
6
- [17 REGRAS DE OURO NORMATIVAS]:
7
- R1. TDD Obrigatório: Escreva ou valide testes unitários ANTES de modificar código de produção.
8
- R2. Branching por Ticket: Trabalhe sempre em branch dedicada exclusivamente com o identificador <TICKET> (ex: PROJ-065878). Nunca comite direto em main.
9
- R3. Pull Request & CI: Todo merge exige PR formal no GitHub com 100% dos checks de CI (TruffleHog, testes e validação) verdes.
10
- R4. Zero Segredos (TruffleHog): NUNCA comite credenciais, arquivos .env, tokens de API ou chaves privadas.
11
- R5. Defesa DevSecOps & OWASP: Imunidade a CWE-78 (Cmd Injection), CWE-79 (XSS), CWE-89 (SQLi), CWE-116 (Sanitização) e CWE-1333 (ReDoS).
12
- R6. Observabilidade Nativa: Exponha /metrics no padrão Prometheus 0.0.4 (CPU, Heap/RSS, latências) e telemetria de fluxo.
13
- R7. Protocolo Dual-Layer: Chat curto e objetivo com tópicos separados por LINHA EM BRANCO DUPLA (\n\n) e links markdown clicáveis.
14
- R8. Bíblia Confluence: Toda decisão arquitetural exige novo ADR canônico no Confluence sincronizado em tempo real.
15
- R9. Governança Jira: Título limpo no Jira (sem [KEY] no summary); mova cards para 'Em andamento' (WIP <= 2) antes de codificar; transição atômica de sprints (zero telas vazias).
16
- R10. Zero Alucinação de Ferramenta: Valide empiricamente as capacidades de APIs externas (Jira, Confluence, GitHub) antes de propor mutações de estado.
17
- R11. Integridade de Documentação: Preserve comentários, docstrings e contratos de API pré-existentes.
18
- R12. Segurança Operacional: NUNCA execute comandos destrutivos (rm -rf, git reset --hard não planejado, drop database).
19
- R13. Ceticismo Adversário (AGENT_QA.md): Audite diffs com frieza cética; forneça testes de quebra; vete quebras de governança ou da Tríade.
20
- R14. Filtro de Sanidade de Ideias: Ideias em docs/IDEAS.md devem ter conexão 100% direta com o domínio e stack real do projeto.
21
- R15. Imutabilidade & Segredos Compulsórios: Requisitos do fluxo são imutáveis e inquebráveis. Valide e obtenha ativamente todas as credenciais (GitHub, Jira, Confluence) com zero falhas silenciosas.
22
- R16. Gate Compulsório da Tríade & Onboarding Bimodal: Veto absoluto a prompts de desenvolvimento de software (criação de código, endpoints ou refatoração) enquanto a Tríade (Git + Jira + Confluence) não estiver 100% configurada, certificada e operando sem falhas e sem alucinações. Diante de comandos prematuros de código, recuse a execução e prescreva a conclusão do roteiro inicial da Tríade.
23
- R17. Integridade Inviolável de Saída: Proibido truncar ou comprimir código (banido "// resto do código aqui" ou omitir imports para poupar tokens). A saída deve ser sempre 100% completa, compilável e com qualidade máxima pronta para produção.
24
-
25
- [TRÍPLICE REGISTRO CONTÍNUO]:
26
- 1. Git: Branch estrita <TICKET> (sem feature/fix/chore) -> Testes locais -> Commit no formato [<TICKET>] - <Ações breves em português> (banidos Conventional Commits e commits sem ticket, inclusive commit inicial [PROJ-1]) -> PR formal -> CI verde -> Merge.
27
- 2. Jira: 'A fazer' -> 'Em andamento' -> Comentário Canônico (15 seções) -> 'Concluído' com transição contínua de sprint.
28
- 3. Confluence: Registro contínuo de novos ADRs e SPECs sincronizados atomicamente.
29
-
30
- [MODOS DE OPERAÇÃO]:
31
- - modo: orchestrator: Coordenação central prescritiva, triagem e despacho de tarefas.
32
- - modo: uiux: Design de interface, UX/UI, Heurísticas de Nielsen, acessibilidade WCAG 2.1 AA e Design Tokens.
33
- - modo: devsecops: Implementação de código robusto, arquitetura limpa e esteiras CI/CD.
34
- - modo: qa: Auditoria adversária independente de PR e governança (autoridade de veto).
35
- - modo: scrum: Gestão ágil, melhoria contínua (PDCA/Ishikawa), higiene de backlog e fluxo Lean ininterrupto.
36
- - modo: sre: Observabilidade contínua (/metrics), telemetria e auto-remediação.
37
- - modo: full-dev: Loop autônomo contínuo: estuda ideia -> implementa -> testa -> registra na Tríade -> avança sem parar.
38
-
39
- [PROTOCOLO DE RESPOSTA IMEDIATA ANTI-LATÊNCIA & ZERO-FILLER TTFT]:
40
- - Zero Filler / Zero Preâmbulo: Proibido iniciar com confirmações conversacionais ou preâmbulos vazios ("Com certeza...", "Vou criar a classe..."). Vá direto à chamada de ferramenta ou código executável, cortando de 4 a 8 segundos de buffer.
41
- - Scaffolding Atômico em 1 Turno (Fast-Path): Ao criar funcionalidades (Entity, Repo, Service, Controller, Test), gere toda a stack em 1 turno atômico via `agent_scaffold_feature`. Banidos múltiplos roundtrips sequenciais de 5 turnos.
42
- - Hot-State Cache & Perfil MCP Compacto: Status de Git e Auth operam sob cache em memória TTL (zero spawn de processos no Windows). Utilize perfil MCP `fast_dev` para cortar 80% do payload de schemas.
43
-
44
- [PROTOCOLO DE SAÍDA NO CHAT]:
45
- • **Feito 1** ([Jira TICKET](url) · [Commit abc](url))
46
- Descrição direta do feito comprovado por testes.
47
-
48
- • **Feito 2** ([Confluence ADR](url) · [PR #X](url))
49
- Detalhe objetivo do teste ou entrega.
50
-
51
- • **Próxima Ação Prescrita (Em Andamento)**
52
- Indicação direta da próxima etapa prioritária sem perguntas passivas.
53
- (Obrigatória linha em branco dupla entre tópicos)
@@ -1,187 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * scripts/a11y_auditor.js
4
- *
5
- * Auditor de Acessibilidade Digital & Design Tokens — WCAG 2.1 AA (AGENT_UIUX / AGENT_QA).
6
- * Inspeciona componentes HTML, JSX e TSX contra violações de acessibilidade, contraste,
7
- * semântica WAI-ARIA, foco visível e padrões de usabilidade (Heurísticas de Nielsen).
8
- *
9
- * Em estrita conformidade com a persona AGENT_UIUX.md e diretrizes de inclusão digital.
10
- */
11
-
12
- 'use strict';
13
-
14
- const fs = require('node:fs');
15
- const path = require('node:path');
16
-
17
- const WCAG_RULES = [
18
- {
19
- id: 'WCAG-1.1.1',
20
- criterion: 'Non-text Content (Nível A)',
21
- name: 'Imagem sem texto alternativo (alt)',
22
- severity: 'CRÍTICA',
23
- pattern: /<(?:img|Image)\b(?![^>]*\balt\s*=)[^>]*>/i,
24
- issue: 'Elemento de imagem não possui o atributo "alt" para tecnologias assistivas.',
25
- remediation: 'Adicione alt="Descrição da imagem" ou alt="" acompanhado de role="presentation" para imagens puramente decorativas.'
26
- },
27
- {
28
- id: 'WCAG-4.1.2-BTN',
29
- criterion: 'Name, Role, Value (Nível A)',
30
- name: 'Botão interativo sem rótulo acessível',
31
- severity: 'ALTA',
32
- pattern: /<(?:button)\b(?![^>]*\b(?:aria-label|aria-labelledby|title)\s*=)[^>]*>\s*<(?:svg|i|span)\b[^>]*>\s*<\/(?:svg|i|span)>\s*<\/button>/i,
33
- issue: 'Botão contendo apenas ícone sem aria-label, aria-labelledby ou texto acessível.',
34
- remediation: 'Inclua aria-label="Ação do botão" ou texto acessível visível/oculto via classe sr-only.'
35
- },
36
- {
37
- id: 'WCAG-1.3.1-INPUT',
38
- criterion: 'Info and Relationships (Nível A)',
39
- name: 'Campo de entrada (input) sem rótulo associado',
40
- severity: 'CRÍTICA',
41
- pattern: /<(?:input)\b(?![^>]*\b(?:type=["'](?:hidden|submit|button|image)["']))(?![^>]*\b(?:aria-label|aria-labelledby|id\s*=))[^>]*>/i,
42
- issue: 'Elemento <input> não possui id para pareamento com <label htmlFor="..."> nem aria-label.',
43
- remediation: 'Adicione um id único ao input pareado com <label htmlFor="id"> ou declare aria-label.'
44
- },
45
- {
46
- id: 'WCAG-2.4.4-LINK',
47
- criterion: 'Link Purpose (In Context) (Nível A)',
48
- name: 'Link com texto vago ou não descritivo',
49
- severity: 'MÉDIA',
50
- pattern: /<a\b[^>]*>\s*(?:clique aqui|click here|saiba mais|read more|veja mais|link)\s*<\/a>/i,
51
- issue: 'Texto de link ambíguo ("clique aqui", "saiba mais") que prejudica a navegação cega por links.',
52
- remediation: 'Substitua por texto descritivo do destino (ex: "Consulte o catálogo de livros").'
53
- },
54
- {
55
- id: 'WCAG-2.4.7-FOCUS',
56
- criterion: 'Focus Visible (Nível AA)',
57
- name: 'Supressão de contorno de foco sem anel acessível',
58
- severity: 'ALTA',
59
- pattern: /className=["'][^"']*\boutline-none\b(?![^"']*\b(?:focus-visible:|focus:ring|focus:border))[^"']*["']/i,
60
- issue: 'Uso de outline-none sem definição de anel alternativo de foco (focus-visible / focus:ring).',
61
- remediation: 'Mantenha o foco visível para usuários de teclado adicionando classes como "focus-visible:ring-2 focus-visible:ring-blue-500".'
62
- },
63
- {
64
- id: 'WCAG-2.4.3-TABINDEX',
65
- criterion: 'Focus Order (Nível A)',
66
- name: 'Uso de tabindex positivo (anti-pattern)',
67
- severity: 'MÉDIA',
68
- pattern: /\btabIndex\s*=\s*(?:\{[1-9][0-9]*\}|["'][1-9][0-9]*["'])/i,
69
- issue: 'tabindex maior que zero altera a ordem natural de tabulação do DOM.',
70
- remediation: 'Utilize tabindex="0" para incluir o elemento no fluxo natural ou reorganize a ordem dos elementos no DOM.'
71
- },
72
- {
73
- id: 'WCAG-3.1.1-LANG',
74
- criterion: 'Language of Page (Nível A)',
75
- name: 'Documento HTML sem atributo de idioma (lang)',
76
- severity: 'ALTA',
77
- pattern: /<html\b(?![^>]*\blang\s*=)[^>]*>/i,
78
- issue: 'Tag <html> sem atributo lang, impedindo sintetizadores de voz de carregar a pronúncia correta.',
79
- remediation: 'Declare o idioma principal do documento: <html lang="pt-BR">.'
80
- }
81
- ];
82
-
83
- class A11yAuditor {
84
- constructor(rules = WCAG_RULES) {
85
- this.rules = rules;
86
- }
87
-
88
- auditCode(code, filename = 'component.tsx') {
89
- const lines = code.split('\n');
90
- const violations = [];
91
-
92
- // 1. Varredura por linha para regras com correspondência em linha única
93
- lines.forEach((line, index) => {
94
- const lineNum = index + 1;
95
- for (const rule of this.rules) {
96
- if (rule.pattern.test(line)) {
97
- violations.push({
98
- ruleId: rule.id,
99
- wcagCriterion: rule.criterion,
100
- name: rule.name,
101
- severity: rule.severity,
102
- line: lineNum,
103
- snippet: line.trim().slice(0, 100),
104
- issue: rule.issue,
105
- remediation: rule.remediation
106
- });
107
- }
108
- }
109
- });
110
-
111
- // 2. Varredura no bloco completo (para tags multilinhas)
112
- for (const rule of this.rules) {
113
- if (rule.pattern.global) {
114
- const matches = code.matchAll(rule.pattern);
115
- for (const match of matches) {
116
- const charIndex = match.index || 0;
117
- const lineNum = code.slice(0, charIndex).split('\n').length;
118
- if (!violations.some(v => v.ruleId === rule.id && v.line === lineNum)) {
119
- violations.push({
120
- ruleId: rule.id,
121
- wcagCriterion: rule.criterion,
122
- name: rule.name,
123
- severity: rule.severity,
124
- line: lineNum,
125
- snippet: match[0].trim().slice(0, 100),
126
- issue: rule.issue,
127
- remediation: rule.remediation
128
- });
129
- }
130
- }
131
- }
132
- }
133
-
134
- const criticalCount = violations.filter(v => v.severity === 'CRÍTICA').length;
135
- const highCount = violations.filter(v => v.severity === 'ALTA').length;
136
- const mediumCount = violations.filter(v => v.severity === 'MÉDIA').length;
137
-
138
- let verdict = 'APROVADO';
139
- if (criticalCount > 0 || highCount > 0) {
140
- verdict = 'REPROVADO';
141
- } else if (mediumCount > 0) {
142
- verdict = 'COM RESSALVAS';
143
- }
144
-
145
- return {
146
- filename,
147
- wcagTarget: 'WCAG 2.1 Nível AA',
148
- verdict,
149
- status: verdict === 'APROVADO' ? 'PASSED' : 'FAILED',
150
- summary: {
151
- totalViolations: violations.length,
152
- criticalCount,
153
- highCount,
154
- mediumCount
155
- },
156
- violations
157
- };
158
- }
159
-
160
- formatReport(audit) {
161
- let md = `## ♿ Relatório de Auditoria de Acessibilidade (WCAG 2.1 AA — AGENT UI/UX)\n\n`;
162
- md += `**Alvo:** \`${audit.filename}\` | **Veredito:** ${audit.verdict === 'APROVADO' ? '✅ APROVADO' : audit.verdict === 'REPROVADO' ? '❌ REPROVADO' : '⚠️ COM RESSALVAS'}\n\n`;
163
- md += `### 📊 Sumário Executivo de Inclusão\n`;
164
- md += `- **Violações Críticas (Impede Leitor de Tela):** ${audit.summary.criticalCount}\n`;
165
- md += `- **Violações Altas (Navegação/Foco):** ${audit.summary.highCount}\n`;
166
- md += `- **Ressalvas Médias:** ${audit.summary.mediumCount}\n\n`;
167
-
168
- if (audit.violations.length > 0) {
169
- md += `### ⚠️ Apontamentos de Acessibilidade Detectados\n\n`;
170
- md += `| Linha | Critério WCAG | Severidade | Problema | Remediação Recomendada |\n`;
171
- md += `| :---: | :--- | :---: | :--- | :--- |\n`;
172
- for (const v of audit.violations) {
173
- md += `| ${v.line} | **${v.wcagCriterion}** (${v.ruleId}) | **${v.severity}** | ${v.issue} | ${v.remediation} |\n`;
174
- }
175
- md += '\n';
176
- } else {
177
- md += `> 🌟 **Componente Acessível:** Nenhuma violação detectada. O componente atende às diretrizes WCAG 2.1 AA.\n\n`;
178
- }
179
-
180
- return md;
181
- }
182
- }
183
-
184
- module.exports = {
185
- A11yAuditor,
186
- WCAG_RULES
187
- };
@@ -1,220 +0,0 @@
1
- /**
2
- * scripts/ast_skeletonizer.js
3
- *
4
- * Extrator Canônico de Esqueleto de Código & Contratos de Interface (Rule 9 — Work Loop).
5
- * "From other modules, read only what they expose (types, function signatures, schemas), never their inner code."
6
- *
7
- * Remove corpos de métodos e implementações internas de classes, gerando um esqueleto com alta
8
- * densidade semântica para prompts de agentes, economizando entre 80% e 92% de tokens de contexto.
9
- * Suporta JavaScript/TypeScript, Java e Python.
10
- */
11
-
12
- 'use strict';
13
-
14
- class AstSkeletonizer {
15
- constructor(options = {}) {
16
- this.charsPerToken = options.charsPerToken || 3.8;
17
- }
18
-
19
- estimateTokens(text = '') {
20
- if (!text) return 0;
21
- return Math.max(1, Math.ceil(text.length / this.charsPerToken));
22
- }
23
-
24
- /**
25
- * Esqueletiza código Java (Remove corpos de métodos mantendo anotações, assinaturas e interfaces)
26
- */
27
- skeletonizeJava(code = '') {
28
- const lines = code.split(/\r?\n/);
29
- const resultLines = [];
30
- let insideMethodBody = false;
31
- let braceDepth = 0;
32
-
33
- for (let i = 0; i < lines.length; i++) {
34
- const line = lines[i];
35
- const trimmed = line.trim();
36
-
37
- if (!insideMethodBody) {
38
- if (trimmed.startsWith('package ') || trimmed.startsWith('import ') || trimmed.startsWith('@') ||
39
- trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*') ||
40
- trimmed.includes('class ') || trimmed.includes('interface ') || trimmed.includes('enum ') ||
41
- trimmed === '' || trimmed === '}') {
42
- resultLines.push(line);
43
- continue;
44
- }
45
-
46
- const isMethodSignature = /\b(public|protected|private|static|final|default)\b.*\(.*\).*/.test(trimmed);
47
- if (isMethodSignature) {
48
- if (trimmed.endsWith('{')) {
49
- const signature = line.substring(0, line.lastIndexOf('{')).trimEnd();
50
- resultLines.push(`${signature} { /* implementation omitted */ }`);
51
- insideMethodBody = true;
52
- braceDepth = 1;
53
- continue;
54
- } else if (trimmed.endsWith(';')) {
55
- resultLines.push(line);
56
- continue;
57
- }
58
- }
59
-
60
- resultLines.push(line);
61
- } else {
62
- for (const char of line) {
63
- if (char === '{') braceDepth++;
64
- if (char === '}') braceDepth--;
65
- }
66
- if (braceDepth <= 0) {
67
- insideMethodBody = false;
68
- braceDepth = 0;
69
- }
70
- }
71
- }
72
-
73
- return resultLines.join('\n');
74
- }
75
-
76
- /**
77
- * Esqueletiza código JS/TS (Mantém exports, interfaces, types e assinaturas, remove corpos de função)
78
- */
79
- skeletonizeJsTs(code = '') {
80
- const lines = code.split(/\r?\n/);
81
- const resultLines = [];
82
- let insideFunction = false;
83
- let braceDepth = 0;
84
-
85
- for (let i = 0; i < lines.length; i++) {
86
- const line = lines[i];
87
- const trimmed = line.trim();
88
-
89
- if (!insideFunction) {
90
- // Preserva imports, declarações de classe, interfaces, types e comentários
91
- if (trimmed.startsWith('import ') || trimmed.startsWith('export type ') || trimmed.startsWith('export interface ') ||
92
- trimmed.startsWith('type ') || trimmed.startsWith('interface ') || trimmed.startsWith('//') ||
93
- trimmed.startsWith('/*') || trimmed.startsWith('*') || (trimmed.startsWith('const ') && trimmed.includes('require(')) ||
94
- trimmed.includes('class ') || trimmed === '' || trimmed === '}') {
95
- resultLines.push(line);
96
- continue;
97
- }
98
-
99
- // Detecta funções soltas ou métodos de classe com abertura de chaves
100
- const isFuncOrMethod = /\b(function|async|get|set|static)\b|\b[\w$]+\s*\([^)]*\)\s*[:\w\s<>]*\{/.test(trimmed);
101
- if (isFuncOrMethod && trimmed.includes('{')) {
102
- const lastBrace = line.lastIndexOf('{');
103
- const signature = line.substring(0, lastBrace).trimEnd();
104
- resultLines.push(`${signature} { /* implementation */ }`);
105
-
106
- // Checa se a função abriu e fechou na mesma linha
107
- let lineDepth = 0;
108
- for (let c = lastBrace; c < line.length; c++) {
109
- if (line[c] === '{') lineDepth++;
110
- if (line[c] === '}') lineDepth--;
111
- }
112
- if (lineDepth > 0) {
113
- insideFunction = true;
114
- braceDepth = lineDepth;
115
- }
116
- continue;
117
- }
118
-
119
- resultLines.push(line);
120
- } else {
121
- for (const char of line) {
122
- if (char === '{') braceDepth++;
123
- if (char === '}') braceDepth--;
124
- }
125
- if (braceDepth <= 0) {
126
- insideFunction = false;
127
- braceDepth = 0;
128
- }
129
- }
130
- }
131
-
132
- return resultLines.join('\n');
133
- }
134
-
135
- /**
136
- * Esqueletiza código Python (Mantém defs, classes e docstrings; substitui corpos por ...)
137
- */
138
- skeletonizePython(code = '') {
139
- const lines = code.split(/\r?\n/);
140
- const resultLines = [];
141
- let insideFunction = false;
142
- let functionIndent = 0;
143
-
144
- for (let i = 0; i < lines.length; i++) {
145
- const line = lines[i];
146
- const trimmed = line.trim();
147
- const currentIndent = (line.match(/^\s*/) || [''])[0].length;
148
-
149
- if (insideFunction) {
150
- if (trimmed === '') continue;
151
- if (currentIndent <= functionIndent && !trimmed.startsWith('#')) {
152
- insideFunction = false;
153
- } else {
154
- // Preserva docstring de 1 linha logo após o def se houver
155
- if ((trimmed.startsWith('"""') || trimmed.startsWith("'''")) && !resultLines[resultLines.length - 1].includes('...')) {
156
- resultLines.push(line);
157
- resultLines.push(' '.repeat(functionIndent + 4) + '...');
158
- }
159
- continue;
160
- }
161
- }
162
-
163
- if (trimmed.startsWith('def ') && trimmed.endsWith(':')) {
164
- resultLines.push(line);
165
- insideFunction = true;
166
- functionIndent = currentIndent;
167
-
168
- // Se a próxima linha for docstring, será tratada na iteração seguinte; caso contrário insere ...
169
- const nextLine = lines[i + 1] ? lines[i + 1].trim() : '';
170
- if (!nextLine.startsWith('"""') && !nextLine.startsWith("'''")) {
171
- resultLines.push(' '.repeat(functionIndent + 4) + '...');
172
- }
173
- continue;
174
- }
175
-
176
- resultLines.push(line);
177
- }
178
-
179
- return resultLines.join('\n');
180
- }
181
-
182
- skeletonize(code = '', language = 'javascript') {
183
- const lang = String(language).toLowerCase().trim();
184
- let skeleton = '';
185
-
186
- if (lang === 'java' || lang === 'jvm') {
187
- skeleton = this.skeletonizeJava(code);
188
- } else if (lang.includes('python') || lang.includes('py')) {
189
- skeleton = this.skeletonizePython(code);
190
- } else {
191
- skeleton = this.skeletonizeJsTs(code);
192
- }
193
-
194
- const originalTokens = this.estimateTokens(code);
195
- const skeletonTokens = this.estimateTokens(skeleton);
196
- const tokensSaved = Math.max(0, originalTokens - skeletonTokens);
197
- const reductionPercent = originalTokens > 0 ? Math.round((tokensSaved / originalTokens) * 100) : 0;
198
-
199
- return {
200
- language: lang,
201
- originalLines: code.split(/\r?\n/).length,
202
- skeletonLines: skeleton.split(/\r?\n/).length,
203
- originalTokens,
204
- skeletonTokens,
205
- tokensSaved,
206
- reductionPercent,
207
- skeletonCode: skeleton
208
- };
209
- }
210
- }
211
-
212
- function extractCodeSkeleton(code, language = 'javascript') {
213
- const skeletonizer = new AstSkeletonizer();
214
- return skeletonizer.skeletonize(code, language);
215
- }
216
-
217
- module.exports = {
218
- AstSkeletonizer,
219
- extractCodeSkeleton
220
- };