agent-master-devsecops 0.0.0-stage → 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.
- package/README.md +204 -2
- package/agents/AGENT_DEVSECOPS.md +32 -0
- package/agents/AGENT_INFRA.md +31 -0
- package/agents/AGENT_ORCHESTRATOR.md +39 -0
- package/agents/AGENT_QA.md +58 -0
- package/agents/AGENT_SCRUM.md +23 -0
- package/agents/AGENT_SRE.md +22 -0
- package/agents/AGENT_UIUX.md +26 -0
- package/docs/ARCHITECTURE.md +152 -0
- package/docs/CALCULATIONS.md +17 -0
- package/docs/CHANGELOG.md +112 -0
- package/docs/ENGINEERING_RULES.md +56 -0
- package/docs/IDEAS.md +17 -0
- package/docs/LOCAL_BACKLOG.md +20 -0
- package/docs/STATE.md +111 -0
- package/docs/playbooks/PLAYBOOK_CIRCUIT_BREAKER_LLM.md +58 -0
- package/docs/playbooks/PLAYBOOK_OPENTELEMETRY_TRACING.md +58 -0
- package/package.json +57 -4
- package/scripts/auditors/a11y_auditor.js +462 -0
- package/scripts/auditors/code_quality_auditor.js +444 -0
- package/scripts/auditors/contract_test_validator.js +396 -0
- package/scripts/auditors/eval_harness.js +213 -0
- package/scripts/auditors/git_hygiene_linter.js +391 -0
- package/scripts/auditors/pr_reviewer.js +627 -0
- package/scripts/auditors/sast_scanner.js +442 -0
- package/scripts/auditors/sca_dependency_auditor.js +673 -0
- package/scripts/bin/bootstrap_cli.js +597 -0
- package/scripts/bin/domain_idea_miner.js +658 -0
- package/scripts/bin/smart_onboarding.js +905 -0
- package/scripts/bin/web_inspector.js +578 -0
- package/scripts/core/architecture_advisor.js +378 -0
- package/scripts/core/ast_skeletonizer.js +413 -0
- package/scripts/core/autonomous_remediation_engine.js +305 -0
- package/scripts/core/circuit_breaker.js +546 -0
- package/scripts/core/context_compressor.js +237 -0
- package/scripts/core/fast_feature_scaffold.js +840 -0
- package/scripts/core/hot_state_cache.js +238 -0
- package/scripts/core/knowledge_gateway.js +888 -0
- package/scripts/core/magic_prompt_generator.js +250 -0
- package/scripts/core/multi_agent_orchestrator.js +421 -0
- package/scripts/core/otel_tracer.js +335 -0
- package/scripts/core/perf_benchmark.js +212 -0
- package/scripts/core/sarif_engine.js +299 -0
- package/scripts/core/sre_remediation_engine.js +236 -0
- package/scripts/core/universal_packager.js +357 -0
- package/scripts/integrations/atlassian_client.js +600 -0
- package/scripts/integrations/atlassian_sync_action.js +576 -0
- package/scripts/integrations/confluence_sync.js +684 -0
- package/scripts/integrations/credentials_guard.js +500 -0
- package/scripts/integrations/jira_manager.js +722 -0
- package/scripts/mcp/handlers/atlassian_handlers.js +300 -0
- package/scripts/mcp/handlers/core_handlers.js +419 -0
- package/scripts/mcp/handlers/qa_handlers.js +502 -0
- package/scripts/mcp/handlers/rules_handlers.js +379 -0
- package/scripts/mcp/handlers/scaffold_handlers.js +334 -0
- package/scripts/mcp/handlers/sre_handlers.js +443 -0
- package/scripts/mcp/resources_registry.js +453 -0
- package/scripts/mcp/server.js +408 -0
- package/scripts/mcp/tool_handlers.js +444 -0
- package/scripts/mcp/tools_registry.js +1123 -0
- package/scripts/mcp_server.js +236 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/core/ast_skeletonizer.js
|
|
3
|
+
*
|
|
4
|
+
* Extrator Canônico de Esqueleto de Código & Contratos de Interface (Princípio 8 & 9).
|
|
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 75% e 92% de tokens de contexto.
|
|
9
|
+
* Suporta JavaScript/TypeScript, Java, Python, Go e Rust.
|
|
10
|
+
*
|
|
11
|
+
* Versão: 5.1.0 Enterprise
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const { createSarifReport } = require('./sarif_engine.js');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Remove comentários e strings para evitar confusão no balanceamento léxico de chaves.
|
|
20
|
+
* @param {string} line
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
function stripStringsAndComments(line = '') {
|
|
24
|
+
if (typeof line !== 'string') return '';
|
|
25
|
+
return line
|
|
26
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
27
|
+
.replace(/\/\/.*$/, '')
|
|
28
|
+
.replace(/`[\s\S]*?`/g, '``')
|
|
29
|
+
.replace(/"(?:[^"\\]|\\.)*"/g, '""')
|
|
30
|
+
.replace(/'(?:[^'\\]|\\.)*'/g, "''");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class AstSkeletonizer {
|
|
34
|
+
constructor(options = {}) {
|
|
35
|
+
this.charsPerToken = options.charsPerToken || 3.8;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
estimateTokens(text = '') {
|
|
39
|
+
if (!text || typeof text !== 'string') return 0;
|
|
40
|
+
return Math.max(1, Math.ceil(text.length / this.charsPerToken));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Esqueletiza código Java (Remove corpos de métodos mantendo anotações, assinaturas e interfaces)
|
|
45
|
+
*/
|
|
46
|
+
skeletonizeJava(code = '') {
|
|
47
|
+
const raw = typeof code === 'string' ? code : String(code || '');
|
|
48
|
+
const lines = raw.split(/\r?\n/);
|
|
49
|
+
const resultLines = [];
|
|
50
|
+
let insideMethodBody = false;
|
|
51
|
+
let braceDepth = 0;
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < lines.length; i++) {
|
|
54
|
+
const line = lines[i];
|
|
55
|
+
const trimmed = line.trim();
|
|
56
|
+
|
|
57
|
+
if (!insideMethodBody) {
|
|
58
|
+
if (trimmed.startsWith('package ') || trimmed.startsWith('import ') || trimmed.startsWith('@') ||
|
|
59
|
+
trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*') ||
|
|
60
|
+
trimmed.includes('class ') || trimmed.includes('interface ') || trimmed.includes('enum ') ||
|
|
61
|
+
trimmed === '' || trimmed === '}') {
|
|
62
|
+
resultLines.push(line);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const isMethodSignature = /\b(public|protected|private|static|final|default)\b.*\(.*\).*/.test(trimmed);
|
|
67
|
+
if (isMethodSignature) {
|
|
68
|
+
if (trimmed.endsWith('{')) {
|
|
69
|
+
const signature = line.substring(0, line.lastIndexOf('{')).trimEnd();
|
|
70
|
+
resultLines.push(`${signature} { /* implementation omitted */ }`);
|
|
71
|
+
insideMethodBody = true;
|
|
72
|
+
braceDepth = 1;
|
|
73
|
+
continue;
|
|
74
|
+
} else if (trimmed.endsWith(';')) {
|
|
75
|
+
resultLines.push(line);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
resultLines.push(line);
|
|
81
|
+
} else {
|
|
82
|
+
const sanitized = stripStringsAndComments(line);
|
|
83
|
+
for (const char of sanitized) {
|
|
84
|
+
if (char === '{') braceDepth++;
|
|
85
|
+
if (char === '}') braceDepth--;
|
|
86
|
+
}
|
|
87
|
+
if (braceDepth <= 0) {
|
|
88
|
+
insideMethodBody = false;
|
|
89
|
+
braceDepth = 0;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return resultLines.join('\n');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Esqueletiza código JS/TS (Mantém exports, interfaces, types e assinaturas, remove corpos de função)
|
|
99
|
+
*/
|
|
100
|
+
skeletonizeJsTs(code = '') {
|
|
101
|
+
const raw = typeof code === 'string' ? code : String(code || '');
|
|
102
|
+
const lines = raw.split(/\r?\n/);
|
|
103
|
+
const resultLines = [];
|
|
104
|
+
let insideFunction = false;
|
|
105
|
+
let braceDepth = 0;
|
|
106
|
+
|
|
107
|
+
for (let i = 0; i < lines.length; i++) {
|
|
108
|
+
const line = lines[i];
|
|
109
|
+
const trimmed = line.trim();
|
|
110
|
+
|
|
111
|
+
if (!insideFunction) {
|
|
112
|
+
if (trimmed.startsWith('import ') || trimmed.startsWith('export type ') || trimmed.startsWith('export interface ') ||
|
|
113
|
+
trimmed.startsWith('type ') || trimmed.startsWith('interface ') || trimmed.startsWith('//') ||
|
|
114
|
+
trimmed.startsWith('/*') || trimmed.startsWith('*') || (trimmed.startsWith('const ') && trimmed.includes('require(')) ||
|
|
115
|
+
trimmed.includes('class ') || trimmed === '' || trimmed === '}') {
|
|
116
|
+
resultLines.push(line);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const isFuncOrMethod = /\b(function|async|get|set|static)\b|\b[\w$]+\s*\([^)]*\)\s*[:\w\s<>]*\{/.test(trimmed);
|
|
121
|
+
if (isFuncOrMethod && trimmed.includes('{')) {
|
|
122
|
+
const lastBrace = line.lastIndexOf('{');
|
|
123
|
+
const signature = line.substring(0, lastBrace).trimEnd();
|
|
124
|
+
resultLines.push(`${signature} { /* implementation */ }`);
|
|
125
|
+
|
|
126
|
+
let lineDepth = 0;
|
|
127
|
+
const sanitizedLine = stripStringsAndComments(line.substring(lastBrace));
|
|
128
|
+
for (let c = 0; c < sanitizedLine.length; c++) {
|
|
129
|
+
if (sanitizedLine[c] === '{') lineDepth++;
|
|
130
|
+
if (sanitizedLine[c] === '}') lineDepth--;
|
|
131
|
+
}
|
|
132
|
+
if (lineDepth > 0) {
|
|
133
|
+
insideFunction = true;
|
|
134
|
+
braceDepth = lineDepth;
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
resultLines.push(line);
|
|
140
|
+
} else {
|
|
141
|
+
const sanitized = stripStringsAndComments(line);
|
|
142
|
+
for (const char of sanitized) {
|
|
143
|
+
if (char === '{') braceDepth++;
|
|
144
|
+
if (char === '}') braceDepth--;
|
|
145
|
+
}
|
|
146
|
+
if (braceDepth <= 0) {
|
|
147
|
+
insideFunction = false;
|
|
148
|
+
braceDepth = 0;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return resultLines.join('\n');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Esqueletiza código Python (Mantém defs, classes e docstrings; substitui corpos por ...)
|
|
158
|
+
*/
|
|
159
|
+
skeletonizePython(code = '') {
|
|
160
|
+
const raw = typeof code === 'string' ? code : String(code || '');
|
|
161
|
+
const lines = raw.split(/\r?\n/);
|
|
162
|
+
const resultLines = [];
|
|
163
|
+
let insideFunction = false;
|
|
164
|
+
let functionIndent = 0;
|
|
165
|
+
|
|
166
|
+
for (let i = 0; i < lines.length; i++) {
|
|
167
|
+
const line = lines[i];
|
|
168
|
+
const trimmed = line.trim();
|
|
169
|
+
const currentIndent = (line.match(/^\s*/) || [''])[0].length;
|
|
170
|
+
|
|
171
|
+
if (insideFunction) {
|
|
172
|
+
if (trimmed === '') continue;
|
|
173
|
+
if (currentIndent <= functionIndent && !trimmed.startsWith('#')) {
|
|
174
|
+
insideFunction = false;
|
|
175
|
+
} else {
|
|
176
|
+
if ((trimmed.startsWith('"""') || trimmed.startsWith("'''")) && !resultLines[resultLines.length - 1].includes('...')) {
|
|
177
|
+
resultLines.push(line);
|
|
178
|
+
resultLines.push(' '.repeat(functionIndent + 4) + '...');
|
|
179
|
+
}
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (trimmed.startsWith('def ') && trimmed.endsWith(':')) {
|
|
185
|
+
resultLines.push(line);
|
|
186
|
+
insideFunction = true;
|
|
187
|
+
functionIndent = currentIndent;
|
|
188
|
+
|
|
189
|
+
const nextLine = lines[i + 1] ? lines[i + 1].trim() : '';
|
|
190
|
+
if (!nextLine.startsWith('"""') && !nextLine.startsWith("'''")) {
|
|
191
|
+
resultLines.push(' '.repeat(functionIndent + 4) + '...');
|
|
192
|
+
}
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
resultLines.push(line);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return resultLines.join('\n');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Esqueletiza código Go (Mantém package, imports, struct, interface e assinaturas func, omite corpos)
|
|
204
|
+
*/
|
|
205
|
+
skeletonizeGo(code = '') {
|
|
206
|
+
const raw = typeof code === 'string' ? code : String(code || '');
|
|
207
|
+
const lines = raw.split(/\r?\n/);
|
|
208
|
+
const resultLines = [];
|
|
209
|
+
let insideFunction = false;
|
|
210
|
+
let braceDepth = 0;
|
|
211
|
+
|
|
212
|
+
for (let i = 0; i < lines.length; i++) {
|
|
213
|
+
const line = lines[i];
|
|
214
|
+
const trimmed = line.trim();
|
|
215
|
+
|
|
216
|
+
if (!insideFunction) {
|
|
217
|
+
if (trimmed.startsWith('package ') || trimmed.startsWith('import ') ||
|
|
218
|
+
trimmed.startsWith('type ') || trimmed.startsWith('//') ||
|
|
219
|
+
trimmed.startsWith('/*') || trimmed.startsWith('*') ||
|
|
220
|
+
trimmed === '' || trimmed === '}') {
|
|
221
|
+
resultLines.push(line);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (trimmed.startsWith('func ') && trimmed.includes('{')) {
|
|
226
|
+
const lastBrace = line.lastIndexOf('{');
|
|
227
|
+
const signature = line.substring(0, lastBrace).trimEnd();
|
|
228
|
+
resultLines.push(`${signature} { /* implementation omitted */ }`);
|
|
229
|
+
|
|
230
|
+
let lineDepth = 0;
|
|
231
|
+
const sanitizedLine = stripStringsAndComments(line.substring(lastBrace));
|
|
232
|
+
for (let c = 0; c < sanitizedLine.length; c++) {
|
|
233
|
+
if (sanitizedLine[c] === '{') lineDepth++;
|
|
234
|
+
if (sanitizedLine[c] === '}') lineDepth--;
|
|
235
|
+
}
|
|
236
|
+
if (lineDepth > 0) {
|
|
237
|
+
insideFunction = true;
|
|
238
|
+
braceDepth = lineDepth;
|
|
239
|
+
}
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
resultLines.push(line);
|
|
244
|
+
} else {
|
|
245
|
+
const sanitized = stripStringsAndComments(line);
|
|
246
|
+
for (const char of sanitized) {
|
|
247
|
+
if (char === '{') braceDepth++;
|
|
248
|
+
if (char === '}') braceDepth--;
|
|
249
|
+
}
|
|
250
|
+
if (braceDepth <= 0) {
|
|
251
|
+
insideFunction = false;
|
|
252
|
+
braceDepth = 0;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return resultLines.join('\n');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Esqueletiza código Rust (Mantém structs, enums, traits e assinaturas fn / pub fn)
|
|
262
|
+
*/
|
|
263
|
+
skeletonizeRust(code = '') {
|
|
264
|
+
const raw = typeof code === 'string' ? code : String(code || '');
|
|
265
|
+
const lines = raw.split(/\r?\n/);
|
|
266
|
+
const resultLines = [];
|
|
267
|
+
let insideFunction = false;
|
|
268
|
+
let braceDepth = 0;
|
|
269
|
+
|
|
270
|
+
for (let i = 0; i < lines.length; i++) {
|
|
271
|
+
const line = lines[i];
|
|
272
|
+
const trimmed = line.trim();
|
|
273
|
+
|
|
274
|
+
if (!insideFunction) {
|
|
275
|
+
if (trimmed.startsWith('use ') || trimmed.startsWith('pub struct ') || trimmed.startsWith('struct ') ||
|
|
276
|
+
trimmed.startsWith('pub enum ') || trimmed.startsWith('enum ') || trimmed.startsWith('pub trait ') ||
|
|
277
|
+
trimmed.startsWith('trait ') || trimmed.startsWith('impl ') || trimmed.startsWith('//') ||
|
|
278
|
+
trimmed.startsWith('/*') || trimmed.startsWith('*') || trimmed.startsWith('#[') ||
|
|
279
|
+
trimmed === '' || trimmed === '}') {
|
|
280
|
+
resultLines.push(line);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const isRustFn = /\b(fn|pub\s+fn|pub\(crate\)\s+fn|async\s+fn)\b/.test(trimmed);
|
|
285
|
+
if (isRustFn && trimmed.includes('{')) {
|
|
286
|
+
const lastBrace = line.lastIndexOf('{');
|
|
287
|
+
const signature = line.substring(0, lastBrace).trimEnd();
|
|
288
|
+
resultLines.push(`${signature} { /* implementation omitted */ }`);
|
|
289
|
+
|
|
290
|
+
let lineDepth = 0;
|
|
291
|
+
const sanitizedLine = stripStringsAndComments(line.substring(lastBrace));
|
|
292
|
+
for (let c = 0; c < sanitizedLine.length; c++) {
|
|
293
|
+
if (sanitizedLine[c] === '{') lineDepth++;
|
|
294
|
+
if (sanitizedLine[c] === '}') lineDepth--;
|
|
295
|
+
}
|
|
296
|
+
if (lineDepth > 0) {
|
|
297
|
+
insideFunction = true;
|
|
298
|
+
braceDepth = lineDepth;
|
|
299
|
+
}
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
resultLines.push(line);
|
|
304
|
+
} else {
|
|
305
|
+
const sanitized = stripStringsAndComments(line);
|
|
306
|
+
for (const char of sanitized) {
|
|
307
|
+
if (char === '{') braceDepth++;
|
|
308
|
+
if (char === '}') braceDepth--;
|
|
309
|
+
}
|
|
310
|
+
if (braceDepth <= 0) {
|
|
311
|
+
insideFunction = false;
|
|
312
|
+
braceDepth = 0;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return resultLines.join('\n');
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
skeletonize(code = '', language = 'javascript') {
|
|
321
|
+
const raw = typeof code === 'string' ? code : String(code || '');
|
|
322
|
+
const lang = String(language || 'javascript').toLowerCase().trim();
|
|
323
|
+
let skeleton = '';
|
|
324
|
+
|
|
325
|
+
if (lang === 'java' || lang === 'jvm') {
|
|
326
|
+
skeleton = this.skeletonizeJava(raw);
|
|
327
|
+
} else if (lang.includes('python') || lang.includes('py')) {
|
|
328
|
+
skeleton = this.skeletonizePython(raw);
|
|
329
|
+
} else if (lang === 'go' || lang === 'golang') {
|
|
330
|
+
skeleton = this.skeletonizeGo(raw);
|
|
331
|
+
} else if (lang === 'rust' || lang === 'rs') {
|
|
332
|
+
skeleton = this.skeletonizeRust(raw);
|
|
333
|
+
} else {
|
|
334
|
+
skeleton = this.skeletonizeJsTs(raw);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const originalTokens = this.estimateTokens(raw);
|
|
338
|
+
const skeletonTokens = this.estimateTokens(skeleton);
|
|
339
|
+
const tokensSaved = Math.max(0, originalTokens - skeletonTokens);
|
|
340
|
+
const reductionPercent = originalTokens > 0 ? Math.round((tokensSaved / originalTokens) * 100) : 0;
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
language: lang,
|
|
344
|
+
originalLines: raw.split(/\r?\n/).length,
|
|
345
|
+
skeletonLines: skeleton.split(/\r?\n/).length,
|
|
346
|
+
originalTokens,
|
|
347
|
+
skeletonTokens,
|
|
348
|
+
tokensSaved,
|
|
349
|
+
reductionPercent,
|
|
350
|
+
skeletonCode: skeleton
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
auditToSarif(code = '', language = 'javascript') {
|
|
355
|
+
const res = this.skeletonize(code, language);
|
|
356
|
+
const findings = [];
|
|
357
|
+
|
|
358
|
+
if (res.reductionPercent < 10 && res.originalLines > 10) {
|
|
359
|
+
findings.push({
|
|
360
|
+
ruleId: 'RULE-AST-001',
|
|
361
|
+
name: 'LowSkeletonReductionRatio',
|
|
362
|
+
severity: 'LOW',
|
|
363
|
+
message: `A taxa de compressão semântica foi de apenas ${res.reductionPercent}%. Considere verificar se o código possui classes/funções reais.`,
|
|
364
|
+
remediation: 'Utilize o esqueleto apenas para módulos com densidade substancial de implementação.'
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return createSarifReport({
|
|
369
|
+
toolName: 'agent-master-ast-skeletonizer',
|
|
370
|
+
rules: [
|
|
371
|
+
{
|
|
372
|
+
id: 'RULE-AST-001',
|
|
373
|
+
name: 'LowSkeletonReductionRatio',
|
|
374
|
+
description: 'Alerta quando a esqueletização não obteve redução significativa de tokens',
|
|
375
|
+
severity: 'LOW',
|
|
376
|
+
cwe: 'CWE-400'
|
|
377
|
+
}
|
|
378
|
+
],
|
|
379
|
+
findings,
|
|
380
|
+
properties: {
|
|
381
|
+
language: res.language,
|
|
382
|
+
reductionPercent: res.reductionPercent,
|
|
383
|
+
tokensSaved: res.tokensSaved
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
formatReport(result) {
|
|
389
|
+
const r = result || this.skeletonize('');
|
|
390
|
+
return [
|
|
391
|
+
'### Relatório Executivo de Esqueletização AST',
|
|
392
|
+
`- **Linguagem:** \`${r.language}\``,
|
|
393
|
+
`- **Linhas:** ${r.originalLines} originais -> ${r.skeletonLines} no esqueleto`,
|
|
394
|
+
`- **Tokens:** ${r.originalTokens} -> ${r.skeletonTokens} (~${r.tokensSaved} tokens economizados)`,
|
|
395
|
+
`- **Eficiência de Redução:** **${r.reductionPercent}%** de economia de contexto`
|
|
396
|
+
].join('\n');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
static extractCodeSkeleton(code, language = 'javascript') {
|
|
400
|
+
const skeletonizer = new AstSkeletonizer();
|
|
401
|
+
return skeletonizer.skeletonize(code, language);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function extractCodeSkeleton(code, language = 'javascript') {
|
|
406
|
+
return AstSkeletonizer.extractCodeSkeleton(code, language);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
module.exports = {
|
|
410
|
+
AstSkeletonizer,
|
|
411
|
+
extractCodeSkeleton,
|
|
412
|
+
stripStringsAndComments
|
|
413
|
+
};
|