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.
- package/README.md +205 -371
- package/agents/AGENT_DEVSECOPS.md +32 -417
- package/agents/AGENT_INFRA.md +31 -0
- package/agents/AGENT_ORCHESTRATOR.md +39 -264
- package/agents/AGENT_QA.md +58 -186
- package/agents/AGENT_SCRUM.md +23 -190
- package/agents/AGENT_SRE.md +22 -173
- package/agents/AGENT_UIUX.md +26 -162
- package/docs/ARCHITECTURE.md +152 -148
- package/docs/CALCULATIONS.md +17 -17
- package/docs/CHANGELOG.md +112 -49
- package/docs/ENGINEERING_RULES.md +56 -252
- package/docs/IDEAS.md +17 -17
- package/docs/LOCAL_BACKLOG.md +20 -0
- package/docs/STATE.md +111 -43
- package/docs/playbooks/PLAYBOOK_CIRCUIT_BREAKER_LLM.md +58 -58
- package/docs/playbooks/PLAYBOOK_OPENTELEMETRY_TRACING.md +58 -58
- package/package.json +59 -47
- 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/{bootstrap_cli.js → bin/bootstrap_cli.js} +597 -468
- package/scripts/bin/domain_idea_miner.js +658 -0
- package/scripts/bin/smart_onboarding.js +905 -0
- package/scripts/{web_inspector.js → bin/web_inspector.js} +578 -355
- 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/{circuit_breaker.js → core/circuit_breaker.js} +546 -330
- 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/{magic_prompt_generator.js → core/magic_prompt_generator.js} +250 -205
- package/scripts/{multi_agent_orchestrator.js → core/multi_agent_orchestrator.js} +421 -258
- package/scripts/{otel_tracer.js → core/otel_tracer.js} +335 -228
- package/scripts/{perf_benchmark.js → core/perf_benchmark.js} +212 -153
- package/scripts/core/sarif_engine.js +299 -0
- package/scripts/{sre_remediation_engine.js → core/sre_remediation_engine.js} +236 -174
- package/scripts/{universal_packager.js → core/universal_packager.js} +357 -313
- 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 -1884
- package/.cursorignore +0 -23
- package/agents/compact/AGENT_ORCHESTRATOR_COMPACTO.md +0 -53
- package/scripts/a11y_auditor.js +0 -187
- package/scripts/ast_skeletonizer.js +0 -220
- package/scripts/atlassian_client.js +0 -238
- package/scripts/atlassian_sync_action.js +0 -269
- package/scripts/code_quality_auditor.js +0 -142
- package/scripts/confluence_sync.js +0 -337
- package/scripts/context_compressor.js +0 -139
- package/scripts/contract_test_validator.js +0 -166
- package/scripts/credentials_guard.js +0 -216
- package/scripts/domain_idea_miner.js +0 -364
- package/scripts/eval_harness.js +0 -100
- package/scripts/fast_feature_scaffold.js +0 -338
- package/scripts/git_hygiene_linter.js +0 -186
- package/scripts/hot_state_cache.js +0 -95
- package/scripts/jira_manager.js +0 -408
- package/scripts/pr_reviewer.js +0 -373
- package/scripts/sast_scanner.js +0 -180
- package/scripts/sca_dependency_auditor.js +0 -167
- package/scripts/smart_onboarding.js +0 -610
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/mcp/handlers/rules_handlers.js
|
|
3
|
+
*
|
|
4
|
+
* Rules, Ideation & Governance MCP Handlers.
|
|
5
|
+
* Despacha chamadas JSON-RPC 2.0 para consulta aos 10 Princípios Canônicos de Engenharia,
|
|
6
|
+
* mapeamento retrocompatível de regras legadas, filtro de sanidade de backlog/ideação (Regra 14)
|
|
7
|
+
* e validação estrita da inviolabilidade de requisitos e credenciais (Regra 15).
|
|
8
|
+
*
|
|
9
|
+
* Versão: 5.1.0 Enterprise
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const fs = require('node:fs');
|
|
15
|
+
const path = require('node:path');
|
|
16
|
+
const { ROOT_DIR } = require('../resources_registry.js');
|
|
17
|
+
const { createSarifReport } = require('../../core/sarif_engine.js');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Catálogo imutável em profundidade de mapeamento das regras legadas (8 a 27)
|
|
21
|
+
* para os 10 Princípios Canônicos da versão 5.0 Enterprise.
|
|
22
|
+
*/
|
|
23
|
+
const LEGACY_RULES_MAP = Object.freeze({
|
|
24
|
+
14: Object.freeze({
|
|
25
|
+
principle: 7,
|
|
26
|
+
title: '14. Curadoria & Revalidação Contextual de Ideias (Ideation Sanity Check)',
|
|
27
|
+
text: 'Consolidada no Princípio 7: Onboarding Bimodal, Resiliência Offline & Sanidade Contextual. É mandatório que o Agente avalie e filtre as ideias geradas por quaisquer subagentes antes de apresentá-las ao usuário, aplicando filtro de sanidade contextual contra overengineering e desconexão de domínio.'
|
|
28
|
+
}),
|
|
29
|
+
18: Object.freeze({
|
|
30
|
+
principle: 5,
|
|
31
|
+
title: '18. Descoberta Compulsória de MCP & Proibição Estrita de Scripts Locais Descartáveis (Native Tool First Principle)',
|
|
32
|
+
text: 'Consolidada no Princípio 5: DevSecOps & Ferramentas Nativas Blindadas por Padrão. É expressamente proibido criar scripts descartáveis no repositório. Priorize ferramentas nativas MCP (agent-master-devsecops, mcp-atlassian) e ferramentas de linha de comando padrão (gh, npm, git).'
|
|
33
|
+
}),
|
|
34
|
+
22: Object.freeze({
|
|
35
|
+
principle: 3,
|
|
36
|
+
title: '22. Integridade e Renderização de Documentação Wiki (Confluence XHTML Storage Format Nativo)',
|
|
37
|
+
text: 'Consolidada no Princípio 3: Rastreabilidade Tríplice & Governança Contínua. Toda documentação sincronizada no Confluence deve utilizar formatação semântica limpa e tags estruturadas XHTML Storage Format (v2).'
|
|
38
|
+
}),
|
|
39
|
+
23: Object.freeze({
|
|
40
|
+
principle: 3,
|
|
41
|
+
title: '23. Descoberta Compulsória de Ticket Jira & Proibição Estrita de Identificadores Alucinados (Traceability Verification First Gate)',
|
|
42
|
+
text: 'Consolidada no Princípio 3 (Rastreabilidade) e Princípio 1 (Verdade Factual). É expressamente proibido supor, adivinhar ou alucinar chaves de tickets Jira sem prévia consulta determinística à API REST do Jira.'
|
|
43
|
+
}),
|
|
44
|
+
24: Object.freeze({
|
|
45
|
+
principle: 5,
|
|
46
|
+
title: '24. Auto-Auditoria Compulsória Pré-Execução & Validação por Linters Nativos (Pre-Flight Self-Compliance Gate)',
|
|
47
|
+
text: 'Consolidada no Princípio 5 (DevSecOps) e Princípio 4 (Qualidade Técnica). Antes de formular propostas de branch, commit ou PR, o agente auto-audita seu output invocando os linters nativos (git_hygiene_linter, sast_scanner, code_quality_auditor).'
|
|
48
|
+
}),
|
|
49
|
+
25: Object.freeze({
|
|
50
|
+
principle: 3,
|
|
51
|
+
title: '25. Ciclo Fechado Compulsório de Pós-Merge & Tríplice Fechamento (Post-Merge Full Lifecycle Closure Gate)',
|
|
52
|
+
text: 'Consolidada no Princípio 3: Rastreabilidade Tríplice. Uma vez mergeado o PR, executar compulsoriamente a transição no Jira para Concluído, registro de ADR no Confluence e git pull na branch main local.'
|
|
53
|
+
}),
|
|
54
|
+
26: Object.freeze({
|
|
55
|
+
principle: 3,
|
|
56
|
+
title: '26. Consolidação Canônica em Página Única no Confluence (Single-Ledger Confluence Integrity)',
|
|
57
|
+
text: 'Consolidada no Princípio 3: Rastreabilidade Tríplice. Livro-razão consolidado append-only para ADRs e governança, preservando a árvore do Confluence.'
|
|
58
|
+
}),
|
|
59
|
+
27: Object.freeze({
|
|
60
|
+
principle: 3,
|
|
61
|
+
title: '27. Rastreabilidade Visual Compulsória na Interface Web do Jira (UI-Visible Web Links Gate)',
|
|
62
|
+
text: 'Consolidada no Princípio 3: Rastreabilidade Tríplice. Vínculos de documentação Confluence devem ser transmitidos como Links da Web acessíveis diretamente na interface gráfica moderna do Jira.'
|
|
63
|
+
})
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Cache em memória reativo para o conteúdo de docs/ENGINEERING_RULES.md
|
|
68
|
+
*/
|
|
69
|
+
let _rulesCache = null;
|
|
70
|
+
let _rulesMtime = null;
|
|
71
|
+
|
|
72
|
+
function getEngineeringRulesContent() {
|
|
73
|
+
const rulesPath = path.join(ROOT_DIR, 'docs', 'ENGINEERING_RULES.md');
|
|
74
|
+
if (!fs.existsSync(rulesPath)) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const stat = fs.statSync(rulesPath);
|
|
79
|
+
if (!_rulesCache || !_rulesMtime || stat.mtimeMs > _rulesMtime) {
|
|
80
|
+
_rulesCache = fs.readFileSync(rulesPath, 'utf8');
|
|
81
|
+
_rulesMtime = stat.mtimeMs;
|
|
82
|
+
}
|
|
83
|
+
return _rulesCache;
|
|
84
|
+
} catch (_) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Helpers funcionais puros para construção determinística de respostas JSON-RPC 2.0 (DRY)
|
|
91
|
+
*/
|
|
92
|
+
function buildSuccessResponse(id, data) {
|
|
93
|
+
const textContent = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
|
|
94
|
+
return {
|
|
95
|
+
jsonrpc: '2.0',
|
|
96
|
+
id,
|
|
97
|
+
result: {
|
|
98
|
+
content: [
|
|
99
|
+
{
|
|
100
|
+
type: 'text',
|
|
101
|
+
text: textContent
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function buildErrorResponse(id, code, message, data = null) {
|
|
109
|
+
const errObj = { code, message };
|
|
110
|
+
if (data) errObj.data = data;
|
|
111
|
+
return {
|
|
112
|
+
jsonrpc: '2.0',
|
|
113
|
+
id,
|
|
114
|
+
error: errObj
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 1. Recupera o texto canônico de uma regra ou princípio (agent_get_rule)
|
|
120
|
+
*/
|
|
121
|
+
function handleGetRule(id, args) {
|
|
122
|
+
try {
|
|
123
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
124
|
+
const num = Number(safeArgs.ruleNumber);
|
|
125
|
+
|
|
126
|
+
if (isNaN(num) || num <= 0) {
|
|
127
|
+
const fallbackText = 'Número da regra não especificado. Consulte os 10 Princípios Canônicos em docs/ENGINEERING_RULES.md.';
|
|
128
|
+
return buildSuccessResponse(id, fallbackText);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const content = getEngineeringRulesContent();
|
|
132
|
+
if (!content) {
|
|
133
|
+
return buildErrorResponse(id, -32603, 'ENGINEERING_RULES.md não encontrado.');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 1. Busca direta pelos 10 Princípios Canônicos (v5.0 Enterprise)
|
|
137
|
+
if (num >= 1 && num <= 10) {
|
|
138
|
+
const regex = new RegExp(`(?:^|\\n)\\s*${num}\\.\\s+\\*\\*(?:Princípio\\s+${num}:)?\\s*([\\s\\S]*?)(?=\\r?\\n\\s*\\d+\\.\\s+\\*\\*|\\r?\\n### |\\r?\\n## |$(?![\\r\\n]))`, 'i');
|
|
139
|
+
const match = content.match(regex);
|
|
140
|
+
if (match) {
|
|
141
|
+
if (safeArgs.format === 'sarif') {
|
|
142
|
+
const sarif = createSarifReport({
|
|
143
|
+
toolName: 'agent-master-rules-engine',
|
|
144
|
+
toolVersion: '5.1.0',
|
|
145
|
+
findings: [],
|
|
146
|
+
properties: {
|
|
147
|
+
ruleNumber: num,
|
|
148
|
+
type: 'CANONICAL_PRINCIPLE',
|
|
149
|
+
content: match[0].trim()
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
return buildSuccessResponse(id, sarif);
|
|
153
|
+
}
|
|
154
|
+
return buildSuccessResponse(id, match[0].trim());
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 2. Mapeamento retrocompatível para regras legadas (8 a 27)
|
|
159
|
+
if (LEGACY_RULES_MAP[num]) {
|
|
160
|
+
const leg = LEGACY_RULES_MAP[num];
|
|
161
|
+
const text = `[REGRA LEGADA ${num} - CONSOLIDAÇÃO CANÔNICA v5.0]\n${leg.title}\n${leg.text}\nReferência: Princípio ${leg.principle} de docs/ENGINEERING_RULES.md`;
|
|
162
|
+
if (safeArgs.format === 'sarif') {
|
|
163
|
+
const sarif = createSarifReport({
|
|
164
|
+
toolName: 'agent-master-rules-engine',
|
|
165
|
+
toolVersion: '5.1.0',
|
|
166
|
+
findings: [],
|
|
167
|
+
properties: {
|
|
168
|
+
ruleNumber: num,
|
|
169
|
+
type: 'LEGACY_RULE_MAPPED',
|
|
170
|
+
consolidatedPrinciple: leg.principle,
|
|
171
|
+
content: text
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return buildSuccessResponse(id, sarif);
|
|
175
|
+
}
|
|
176
|
+
return buildSuccessResponse(id, text);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 3. Fallback para busca genérica ou aviso de consolidação
|
|
180
|
+
const fallbackRegex = new RegExp(`(?:^|\\n)\\s*${num}\\.\\s+([\\s\\S]*?)(?=\\r?\\n\\s*\\d+\\.\\s+\\*\\*|\\r?\\n### |\\r?\\n## |$(?![\\r\\n]))`);
|
|
181
|
+
const match = content.match(fallbackRegex);
|
|
182
|
+
const ruleText = match
|
|
183
|
+
? match[0].trim()
|
|
184
|
+
: `Regra ${num} consolidada na v5.0 Enterprise. Consulte os 10 Princípios Canônicos em docs/ENGINEERING_RULES.md.`;
|
|
185
|
+
|
|
186
|
+
if (safeArgs.format === 'sarif') {
|
|
187
|
+
const sarif = createSarifReport({
|
|
188
|
+
toolName: 'agent-master-rules-engine',
|
|
189
|
+
toolVersion: '5.1.0',
|
|
190
|
+
findings: [],
|
|
191
|
+
properties: {
|
|
192
|
+
ruleNumber: num,
|
|
193
|
+
type: 'GENERIC_RULE_SEARCH',
|
|
194
|
+
content: ruleText
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
return buildSuccessResponse(id, sarif);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return buildSuccessResponse(id, ruleText);
|
|
201
|
+
} catch (err) {
|
|
202
|
+
return buildErrorResponse(id, -32603, `Falha em handleGetRule: ${err.message}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 2. Filtro de Sanidade Contextual & Anti-Overengineering de Ideias (agent_validate_idea / Regra 14)
|
|
208
|
+
*/
|
|
209
|
+
function handleValidateIdea(id, args) {
|
|
210
|
+
try {
|
|
211
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
212
|
+
const ideaTitle = String(safeArgs.ideaTitle || '').trim();
|
|
213
|
+
const ideaDescription = String(safeArgs.ideaDescription || '').trim();
|
|
214
|
+
const projectStack = String(safeArgs.projectStack || '').trim();
|
|
215
|
+
const projectDomain = String(safeArgs.projectDomain || '').trim();
|
|
216
|
+
const format = safeArgs.format || 'json';
|
|
217
|
+
|
|
218
|
+
const fullIdeaText = `${ideaTitle} ${ideaDescription}`;
|
|
219
|
+
const fullContextText = `${projectStack} ${projectDomain}`;
|
|
220
|
+
|
|
221
|
+
const isOffDomain = /blockchain|crypto|metaverse|web3/i.test(fullIdeaText) && !/crypto|blockchain/i.test(projectDomain);
|
|
222
|
+
const isOverengineering = /kubernetes|kafka|microservices|distributed/i.test(fullIdeaText) && /bot|cli|pequeno|monolito|sqlite/i.test(fullContextText);
|
|
223
|
+
|
|
224
|
+
let approved = true;
|
|
225
|
+
let verdict = 'APROVADA';
|
|
226
|
+
let rationale = 'A ideia apresenta coerência arquitetural com a stack e o domínio fornecidos.';
|
|
227
|
+
|
|
228
|
+
if (isOffDomain) {
|
|
229
|
+
approved = false;
|
|
230
|
+
verdict = 'REJEITADA (Critério 1: Desconexão de Domínio)';
|
|
231
|
+
rationale = 'A proposta introduz componentes fora do propósito e regras de negócio da aplicação.';
|
|
232
|
+
} else if (isOverengineering) {
|
|
233
|
+
approved = false;
|
|
234
|
+
verdict = 'REJEITADA (Critério 2: Overengineering / Complexidade Artificial)';
|
|
235
|
+
rationale = 'A solução proposta introduz complexidade operacional desproporcional à escala do projeto.';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (format === 'sarif') {
|
|
239
|
+
const findings = [];
|
|
240
|
+
if (!approved) {
|
|
241
|
+
findings.push({
|
|
242
|
+
ruleId: isOffDomain ? 'RULE-IDEA-001' : 'RULE-IDEA-002',
|
|
243
|
+
severity: 'HIGH',
|
|
244
|
+
filename: 'docs/IDEAS.md',
|
|
245
|
+
line: 1,
|
|
246
|
+
column: 1,
|
|
247
|
+
snippet: ideaTitle || 'Ideia sem título',
|
|
248
|
+
message: `${verdict}: ${rationale}`,
|
|
249
|
+
remediation: isOffDomain
|
|
250
|
+
? 'Reorientar a proposta para os limites estritos do domínio do negócio.'
|
|
251
|
+
: 'Simplificar a arquitetura adotando soluções nativas e monólito modular.'
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const sarif = createSarifReport({
|
|
256
|
+
toolName: 'agent-master-sanity-filter',
|
|
257
|
+
toolVersion: '5.1.0',
|
|
258
|
+
findings,
|
|
259
|
+
properties: {
|
|
260
|
+
idea: ideaTitle,
|
|
261
|
+
verdict,
|
|
262
|
+
approved,
|
|
263
|
+
rationale,
|
|
264
|
+
rule: 'Regra 14 - Ideation Sanity Filter'
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
return buildSuccessResponse(id, sarif);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return buildSuccessResponse(id, {
|
|
271
|
+
idea: ideaTitle,
|
|
272
|
+
veredito: verdict,
|
|
273
|
+
aprovado: approved,
|
|
274
|
+
justificativa: rationale,
|
|
275
|
+
regra: 'Regra 14 - Ideation Sanity Filter'
|
|
276
|
+
});
|
|
277
|
+
} catch (err) {
|
|
278
|
+
return buildErrorResponse(id, -32603, `Falha em handleValidateIdea: ${err.message}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* 3. Validação Estrita da Inviolabilidade de Requisitos & Credenciais (agent_validate_rule15 / Regra 15)
|
|
284
|
+
*/
|
|
285
|
+
function handleValidateRule15(id, args) {
|
|
286
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
287
|
+
const { validateRule15, auditToSarif } = require('../../integrations/credentials_guard.js');
|
|
288
|
+
try {
|
|
289
|
+
const res = validateRule15({
|
|
290
|
+
failFast: Boolean(safeArgs.failFast),
|
|
291
|
+
requireGitHub: safeArgs.requireGitHub !== false,
|
|
292
|
+
requireAtlassian: safeArgs.requireAtlassian !== false
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
if (safeArgs.format === 'sarif') {
|
|
296
|
+
const sarif = auditToSarif(res);
|
|
297
|
+
return buildSuccessResponse(id, sarif);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return buildSuccessResponse(id, {
|
|
301
|
+
status: res.valid ? 'SUCCESS' : 'BLOCKED',
|
|
302
|
+
rule: 'Regra 15 - Imutabilidade de Requisitos & Validação Compulsória de Segredos',
|
|
303
|
+
valid: res.valid,
|
|
304
|
+
missing: res.missing,
|
|
305
|
+
remediation: res.remediation,
|
|
306
|
+
atlassianConfigured: res.atlassian.isConfigured,
|
|
307
|
+
githubAuthenticated: res.github.isAuthenticated
|
|
308
|
+
});
|
|
309
|
+
} catch (err) {
|
|
310
|
+
return buildErrorResponse(id, -32015, err.message, {
|
|
311
|
+
missing: err.missingRequirements || [],
|
|
312
|
+
remediation: err.remediationSteps || []
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Classe Canônica RulesHandlers
|
|
319
|
+
* Fornece API orientada a objetos com suporte a métodos estáticos e de instância.
|
|
320
|
+
*/
|
|
321
|
+
class RulesHandlers {
|
|
322
|
+
static get LEGACY_RULES() {
|
|
323
|
+
return LEGACY_RULES_MAP;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
static buildSuccessResponse(id, data) {
|
|
327
|
+
return buildSuccessResponse(id, data);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
static buildErrorResponse(id, code, message, data = null) {
|
|
331
|
+
return buildErrorResponse(id, code, message, data);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
static handleGetRule(id, args) {
|
|
335
|
+
return handleGetRule(id, args);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
static handleValidateIdea(id, args) {
|
|
339
|
+
return handleValidateIdea(id, args);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
static handleValidateRule15(id, args) {
|
|
343
|
+
return handleValidateRule15(id, args);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
get LEGACY_RULES() {
|
|
347
|
+
return RulesHandlers.LEGACY_RULES;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
buildSuccessResponse(id, data) {
|
|
351
|
+
return RulesHandlers.buildSuccessResponse(id, data);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
buildErrorResponse(id, code, message, data = null) {
|
|
355
|
+
return RulesHandlers.buildErrorResponse(id, code, message, data);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
handleGetRule(id, args) {
|
|
359
|
+
return RulesHandlers.handleGetRule(id, args);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
handleValidateIdea(id, args) {
|
|
363
|
+
return RulesHandlers.handleValidateIdea(id, args);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
handleValidateRule15(id, args) {
|
|
367
|
+
return RulesHandlers.handleValidateRule15(id, args);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
module.exports = {
|
|
372
|
+
RulesHandlers,
|
|
373
|
+
LEGACY_RULES_MAP,
|
|
374
|
+
buildSuccessResponse,
|
|
375
|
+
buildErrorResponse,
|
|
376
|
+
handleGetRule,
|
|
377
|
+
handleValidateIdea,
|
|
378
|
+
handleValidateRule15
|
|
379
|
+
};
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scripts/mcp/handlers/scaffold_handlers.js
|
|
3
|
+
*
|
|
4
|
+
* Scaffold, AST & Code Generation MCP Handlers.
|
|
5
|
+
* Despacha chamadas JSON-RPC 2.0 para geração atômica de features (Fast-Path / Princípio 7),
|
|
6
|
+
* extração de esqueletos AST (ast_skeletonizer), compressão de contexto LLM (context_compressor),
|
|
7
|
+
* empacotamento universal de personas (universal_packager), bootstrap de ambientes IDE
|
|
8
|
+
* e exportação de Magic Prompts.
|
|
9
|
+
*
|
|
10
|
+
* Versão: 5.1.0 Enterprise
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
const path = require('node:path');
|
|
16
|
+
const { ROOT_DIR } = require('../resources_registry.js');
|
|
17
|
+
const { createSarifReport } = require('../../core/sarif_engine.js');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Helpers funcionais puros para construção determinística de respostas JSON-RPC 2.0 (DRY)
|
|
21
|
+
*/
|
|
22
|
+
function buildSuccessResponse(id, data) {
|
|
23
|
+
const textContent = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
|
|
24
|
+
return {
|
|
25
|
+
jsonrpc: '2.0',
|
|
26
|
+
id,
|
|
27
|
+
result: {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: textContent
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function buildErrorResponse(id, code, message, data = null) {
|
|
39
|
+
const errObj = { code, message };
|
|
40
|
+
if (data) errObj.data = data;
|
|
41
|
+
return {
|
|
42
|
+
jsonrpc: '2.0',
|
|
43
|
+
id,
|
|
44
|
+
error: errObj
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 1. Geração de Manifestos e Configurações de IDE (agent_generate_ide_plugins)
|
|
50
|
+
*/
|
|
51
|
+
function handleGenerateIdePlugins(id, args) {
|
|
52
|
+
try {
|
|
53
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
54
|
+
const { generateIdeConfigs } = require('../../core/universal_packager.js');
|
|
55
|
+
const target = safeArgs.target || 'all';
|
|
56
|
+
const targetDir = safeArgs.targetDir || ROOT_DIR;
|
|
57
|
+
const generated = generateIdeConfigs(targetDir, { target, dryRun: Boolean(safeArgs.dryRun) });
|
|
58
|
+
|
|
59
|
+
return buildSuccessResponse(id, {
|
|
60
|
+
status: 'SUCCESS',
|
|
61
|
+
generatedFiles: generated,
|
|
62
|
+
target,
|
|
63
|
+
targetDir
|
|
64
|
+
});
|
|
65
|
+
} catch (err) {
|
|
66
|
+
return buildErrorResponse(id, -32603, `Falha em handleGenerateIdePlugins: ${err.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 2. Compressão de Contexto e Estimativa de Tokens (agent_compress_context)
|
|
72
|
+
*/
|
|
73
|
+
function handleCompressContext(id, args) {
|
|
74
|
+
try {
|
|
75
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
76
|
+
const { generateCompactPrompt, compressCustomText, estimateTokens } = require('../../core/context_compressor.js');
|
|
77
|
+
const customText = safeArgs.text;
|
|
78
|
+
const maxTokens = Number(safeArgs.maxTokens) || 1500;
|
|
79
|
+
|
|
80
|
+
let compressedText = '';
|
|
81
|
+
if (customText) {
|
|
82
|
+
compressedText = compressCustomText(customText, maxTokens);
|
|
83
|
+
} else {
|
|
84
|
+
compressedText = generateCompactPrompt();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const tokenCount = estimateTokens(compressedText);
|
|
88
|
+
return buildSuccessResponse(id, {
|
|
89
|
+
status: 'SUCCESS',
|
|
90
|
+
tokensEstimados: tokenCount,
|
|
91
|
+
limiteTokens: maxTokens,
|
|
92
|
+
dentroDoOrcamento: tokenCount <= maxTokens,
|
|
93
|
+
tamanhoCaracteres: compressedText.length,
|
|
94
|
+
textoCompactado: compressedText
|
|
95
|
+
});
|
|
96
|
+
} catch (err) {
|
|
97
|
+
return buildErrorResponse(id, -32603, `Falha em handleCompressContext: ${err.message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 3. Exportação de Bundles Universais para LLMs/Plataformas (agent_export_universal_bundle)
|
|
103
|
+
*/
|
|
104
|
+
function handleExportUniversalBundle(id, args) {
|
|
105
|
+
try {
|
|
106
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
107
|
+
const { UniversalPackager } = require('../../core/universal_packager.js');
|
|
108
|
+
const packager = new UniversalPackager();
|
|
109
|
+
const platform = safeArgs.platform || 'all';
|
|
110
|
+
const targetDir = safeArgs.targetDir || path.join(ROOT_DIR, 'dist', 'bundles', platform);
|
|
111
|
+
const dryRun = safeArgs.dryRun;
|
|
112
|
+
|
|
113
|
+
const result = packager.exportProfile(platform, targetDir, { dryRun });
|
|
114
|
+
|
|
115
|
+
return buildSuccessResponse(id, {
|
|
116
|
+
status: 'SUCCESS',
|
|
117
|
+
exportResult: result
|
|
118
|
+
});
|
|
119
|
+
} catch (err) {
|
|
120
|
+
return buildErrorResponse(id, -32603, `Falha em handleExportUniversalBundle: ${err.message}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 4. Bootstrap de Ambiente e Provisionamento de Arquivos Canônicos (agent_bootstrap_environment)
|
|
126
|
+
*/
|
|
127
|
+
function handleBootstrapEnvironment(id, args) {
|
|
128
|
+
try {
|
|
129
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
130
|
+
const { bootstrapEnvironment } = require('../../bin/bootstrap_cli.js');
|
|
131
|
+
const targetDir = safeArgs.targetDir || ROOT_DIR;
|
|
132
|
+
const dryRun = safeArgs.dryRun;
|
|
133
|
+
const platforms = safeArgs.platforms;
|
|
134
|
+
|
|
135
|
+
const result = bootstrapEnvironment(targetDir, { dryRun, platforms });
|
|
136
|
+
|
|
137
|
+
if (safeArgs.format === 'sarif') {
|
|
138
|
+
const sarif = createSarifReport({
|
|
139
|
+
toolName: 'agent-master-bootstrap-cli',
|
|
140
|
+
toolVersion: '5.1.0',
|
|
141
|
+
findings: [],
|
|
142
|
+
properties: {
|
|
143
|
+
status: result.status,
|
|
144
|
+
dryRun: result.dryRun,
|
|
145
|
+
configuredPlatforms: result.configuredPlatforms,
|
|
146
|
+
copiedFilesCount: (result.copiedFiles && result.copiedFiles.length) || 0
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return buildSuccessResponse(id, sarif);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return buildSuccessResponse(id, result);
|
|
153
|
+
} catch (err) {
|
|
154
|
+
return buildErrorResponse(id, -32603, `Falha em handleBootstrapEnvironment: ${err.message}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 5. Geração de Magic Prompt e Bookmarklet (agent_generate_magic_prompt)
|
|
160
|
+
*/
|
|
161
|
+
function handleGenerateMagicPrompt(id, args) {
|
|
162
|
+
try {
|
|
163
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
164
|
+
const { MagicPromptGenerator } = require('../../core/magic_prompt_generator.js');
|
|
165
|
+
const generator = new MagicPromptGenerator(ROOT_DIR);
|
|
166
|
+
const targetDir = safeArgs.targetDir || path.join(ROOT_DIR, 'dist', 'magic_prompt');
|
|
167
|
+
const dryRun = safeArgs.dryRun;
|
|
168
|
+
|
|
169
|
+
const result = generator.exportArtifacts(targetDir, { dryRun });
|
|
170
|
+
|
|
171
|
+
return buildSuccessResponse(id, result);
|
|
172
|
+
} catch (err) {
|
|
173
|
+
return buildErrorResponse(id, -32603, `Falha em handleGenerateMagicPrompt: ${err.message}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 6. Esqueletização AST de Código-Fonte (agent_extract_code_skeleton)
|
|
179
|
+
*/
|
|
180
|
+
function handleExtractCodeSkeleton(id, args) {
|
|
181
|
+
try {
|
|
182
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
183
|
+
const { extractCodeSkeleton } = require('../../core/ast_skeletonizer.js');
|
|
184
|
+
const code = String(safeArgs.code || '');
|
|
185
|
+
const language = String(safeArgs.language || 'javascript');
|
|
186
|
+
const result = extractCodeSkeleton(code, language);
|
|
187
|
+
|
|
188
|
+
if (safeArgs.format === 'sarif') {
|
|
189
|
+
const sarif = createSarifReport({
|
|
190
|
+
toolName: 'agent-master-ast-skeletonizer',
|
|
191
|
+
toolVersion: '5.1.0',
|
|
192
|
+
findings: [],
|
|
193
|
+
properties: {
|
|
194
|
+
language,
|
|
195
|
+
tokenEconomyPercent: result.tokenEconomyPercent || 0,
|
|
196
|
+
originalTokens: result.originalTokens || 0,
|
|
197
|
+
skeletonTokens: result.skeletonTokens || 0,
|
|
198
|
+
skeletonCode: result.skeletonCode
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
return buildSuccessResponse(id, sarif);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return buildSuccessResponse(id, result);
|
|
205
|
+
} catch (err) {
|
|
206
|
+
return buildErrorResponse(id, -32603, `Falha em handleExtractCodeSkeleton: ${err.message}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* 7. Scaffolding Atômico Rápido de Features (agent_scaffold_feature / Fast-Path)
|
|
212
|
+
*/
|
|
213
|
+
function handleScaffoldFeature(id, args) {
|
|
214
|
+
try {
|
|
215
|
+
const safeArgs = args && typeof args === 'object' ? args : {};
|
|
216
|
+
const { scaffoldFeatureFast } = require('../../core/fast_feature_scaffold.js');
|
|
217
|
+
const targetDir = safeArgs.targetDir ? path.resolve(safeArgs.targetDir) : process.cwd();
|
|
218
|
+
const result = scaffoldFeatureFast(safeArgs, {
|
|
219
|
+
rootDir: targetDir,
|
|
220
|
+
writeToDisk: Boolean(safeArgs.writeToDisk)
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
if (safeArgs.format === 'sarif') {
|
|
224
|
+
const sarif = createSarifReport({
|
|
225
|
+
toolName: 'agent-master-fast-feature-scaffold',
|
|
226
|
+
toolVersion: '5.1.0',
|
|
227
|
+
findings: [],
|
|
228
|
+
properties: {
|
|
229
|
+
status: result.status,
|
|
230
|
+
featureName: result.featureName,
|
|
231
|
+
stack: result.stack,
|
|
232
|
+
filesGeneratedCount: result.filesGeneratedCount,
|
|
233
|
+
executionTimeMs: result.executionTimeMs
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
return buildSuccessResponse(id, sarif);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return buildSuccessResponse(id, result);
|
|
240
|
+
} catch (err) {
|
|
241
|
+
return buildErrorResponse(id, -32603, `Falha em handleScaffoldFeature: ${err.message}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Classe Canônica ScaffoldHandlers
|
|
247
|
+
* Fornece API orientada a objetos com suporte a métodos estáticos e de instância.
|
|
248
|
+
*/
|
|
249
|
+
class ScaffoldHandlers {
|
|
250
|
+
static buildSuccessResponse(id, data) {
|
|
251
|
+
return buildSuccessResponse(id, data);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
static buildErrorResponse(id, code, message, data = null) {
|
|
255
|
+
return buildErrorResponse(id, code, message, data);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
static handleGenerateIdePlugins(id, args) {
|
|
259
|
+
return handleGenerateIdePlugins(id, args);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
static handleCompressContext(id, args) {
|
|
263
|
+
return handleCompressContext(id, args);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
static handleExportUniversalBundle(id, args) {
|
|
267
|
+
return handleExportUniversalBundle(id, args);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
static handleBootstrapEnvironment(id, args) {
|
|
271
|
+
return handleBootstrapEnvironment(id, args);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
static handleGenerateMagicPrompt(id, args) {
|
|
275
|
+
return handleGenerateMagicPrompt(id, args);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
static handleExtractCodeSkeleton(id, args) {
|
|
279
|
+
return handleExtractCodeSkeleton(id, args);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
static handleScaffoldFeature(id, args) {
|
|
283
|
+
return handleScaffoldFeature(id, args);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
buildSuccessResponse(id, data) {
|
|
287
|
+
return ScaffoldHandlers.buildSuccessResponse(id, data);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
buildErrorResponse(id, code, message, data = null) {
|
|
291
|
+
return ScaffoldHandlers.buildErrorResponse(id, code, message, data);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
handleGenerateIdePlugins(id, args) {
|
|
295
|
+
return ScaffoldHandlers.handleGenerateIdePlugins(id, args);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
handleCompressContext(id, args) {
|
|
299
|
+
return ScaffoldHandlers.handleCompressContext(id, args);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
handleExportUniversalBundle(id, args) {
|
|
303
|
+
return ScaffoldHandlers.handleExportUniversalBundle(id, args);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
handleBootstrapEnvironment(id, args) {
|
|
307
|
+
return ScaffoldHandlers.handleBootstrapEnvironment(id, args);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
handleGenerateMagicPrompt(id, args) {
|
|
311
|
+
return ScaffoldHandlers.handleGenerateMagicPrompt(id, args);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
handleExtractCodeSkeleton(id, args) {
|
|
315
|
+
return ScaffoldHandlers.handleExtractCodeSkeleton(id, args);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
handleScaffoldFeature(id, args) {
|
|
319
|
+
return ScaffoldHandlers.handleScaffoldFeature(id, args);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
module.exports = {
|
|
324
|
+
ScaffoldHandlers,
|
|
325
|
+
buildSuccessResponse,
|
|
326
|
+
buildErrorResponse,
|
|
327
|
+
handleGenerateIdePlugins,
|
|
328
|
+
handleCompressContext,
|
|
329
|
+
handleExportUniversalBundle,
|
|
330
|
+
handleBootstrapEnvironment,
|
|
331
|
+
handleGenerateMagicPrompt,
|
|
332
|
+
handleExtractCodeSkeleton,
|
|
333
|
+
handleScaffoldFeature
|
|
334
|
+
};
|