@creative-ia/cortex 1.0.5

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 (64) hide show
  1. package/README.md +41 -0
  2. package/dist/config/cloud-proxy.d.ts +15 -0
  3. package/dist/config/cloud-proxy.js +63 -0
  4. package/dist/config/cloudwatch-store.d.ts +13 -0
  5. package/dist/config/cloudwatch-store.js +66 -0
  6. package/dist/config/license.d.ts +29 -0
  7. package/dist/config/license.js +165 -0
  8. package/dist/config/ssm-store.d.ts +2 -0
  9. package/dist/config/ssm-store.js +38 -0
  10. package/dist/config/telemetry.d.ts +17 -0
  11. package/dist/config/telemetry.js +93 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +460 -0
  14. package/dist/knowledge/dynamo-store.d.ts +17 -0
  15. package/dist/knowledge/dynamo-store.js +85 -0
  16. package/dist/knowledge/embeddings.d.ts +2 -0
  17. package/dist/knowledge/embeddings.js +36 -0
  18. package/dist/knowledge/loader.d.ts +8 -0
  19. package/dist/knowledge/loader.js +57 -0
  20. package/dist/lambda-package.zip +0 -0
  21. package/dist/lambda.d.ts +22 -0
  22. package/dist/lambda.js +496 -0
  23. package/dist/package.json +1 -0
  24. package/dist/tools/advance-process.d.ts +7 -0
  25. package/dist/tools/advance-process.js +128 -0
  26. package/dist/tools/analyze-code.d.ts +7 -0
  27. package/dist/tools/analyze-code.js +131 -0
  28. package/dist/tools/analyze-docs.d.ts +8 -0
  29. package/dist/tools/analyze-docs.js +147 -0
  30. package/dist/tools/config-registry.d.ts +3 -0
  31. package/dist/tools/config-registry.js +20 -0
  32. package/dist/tools/create-process.d.ts +6 -0
  33. package/dist/tools/create-process.js +257 -0
  34. package/dist/tools/decompose-epic.d.ts +7 -0
  35. package/dist/tools/decompose-epic.js +603 -0
  36. package/dist/tools/diagrams.d.ts +51 -0
  37. package/dist/tools/diagrams.js +304 -0
  38. package/dist/tools/generate-report.d.ts +9 -0
  39. package/dist/tools/generate-report.js +891 -0
  40. package/dist/tools/generate-wiki.d.ts +10 -0
  41. package/dist/tools/generate-wiki.js +700 -0
  42. package/dist/tools/get-architecture.d.ts +6 -0
  43. package/dist/tools/get-architecture.js +78 -0
  44. package/dist/tools/get-code-standards.d.ts +7 -0
  45. package/dist/tools/get-code-standards.js +52 -0
  46. package/dist/tools/init-process.d.ts +7 -0
  47. package/dist/tools/init-process.js +82 -0
  48. package/dist/tools/knowledge-crud.d.ts +26 -0
  49. package/dist/tools/knowledge-crud.js +142 -0
  50. package/dist/tools/logo-base64.d.ts +1 -0
  51. package/dist/tools/logo-base64.js +1 -0
  52. package/dist/tools/logs-query.d.ts +15 -0
  53. package/dist/tools/logs-query.js +46 -0
  54. package/dist/tools/reverse-engineer.d.ts +13 -0
  55. package/dist/tools/reverse-engineer.js +956 -0
  56. package/dist/tools/semantic-search.d.ts +7 -0
  57. package/dist/tools/semantic-search.js +68 -0
  58. package/dist/tools/update-process.d.ts +17 -0
  59. package/dist/tools/update-process.js +195 -0
  60. package/dist/tools/validate-idea.d.ts +7 -0
  61. package/dist/tools/validate-idea.js +339 -0
  62. package/dist/tools/validate-process.d.ts +6 -0
  63. package/dist/tools/validate-process.js +102 -0
  64. package/package.json +31 -0
@@ -0,0 +1,7 @@
1
+ import { type License } from "../config/license.js";
2
+ export declare function semanticSearch(params: {
3
+ query: string;
4
+ domain?: string;
5
+ limit?: number;
6
+ license?: License;
7
+ }): Promise<string>;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Tool MCP: semantic_search — Busca semântica no knowledge base via Bedrock Embeddings.
3
+ *
4
+ * Fluxo:
5
+ * 1. Gera embedding da query do usuário
6
+ * 2. Carrega todos os registros do(s) domain(s)
7
+ * 3. Gera embedding de cada registro (título + conteúdo truncado)
8
+ * 4. Calcula cosine similarity
9
+ * 5. Retorna top-N mais relevantes
10
+ *
11
+ * Cache: embeddings são gerados on-the-fly (dataset pequeno, ~100 registros).
12
+ * Para datasets maiores, considerar cache em DynamoDB.
13
+ */
14
+ import { getEmbedding, cosineSimilarity } from "../knowledge/embeddings.js";
15
+ import { queryByDomain } from "../knowledge/dynamo-store.js";
16
+ import { filterAllowedDomains } from "../config/license.js";
17
+ const ALL_DOMAINS = [
18
+ "decisions", "changelog", "troubleshooting", "glossary",
19
+ "integrations", "lessons-learned", "pending", "ports",
20
+ "stakeholders", "environments",
21
+ ];
22
+ export async function semanticSearch(params) {
23
+ const limit = params.limit || 5;
24
+ const allDomains = params.domain ? [params.domain] : ALL_DOMAINS;
25
+ const domains = params.license ? filterAllowedDomains(params.license, allDomains) : allDomains;
26
+ // 1. Get query embedding
27
+ const queryEmb = await getEmbedding(params.query);
28
+ // 2. Load all entries from target domains
29
+ const allEntries = [];
30
+ for (const d of domains) {
31
+ const entries = await queryByDomain(d, 200);
32
+ allEntries.push(...entries);
33
+ }
34
+ if (allEntries.length === 0) {
35
+ return "Nenhum registro encontrado nos domains selecionados.";
36
+ }
37
+ // 3. Score each entry
38
+ const scored = [];
39
+ for (const entry of allEntries) {
40
+ const text = `${entry.title}. ${entry.content.slice(0, 500)}`;
41
+ try {
42
+ const entryEmb = await getEmbedding(text);
43
+ const score = cosineSimilarity(queryEmb, entryEmb);
44
+ scored.push({ entry, score });
45
+ }
46
+ catch {
47
+ // Skip entries that fail embedding
48
+ }
49
+ }
50
+ // 4. Sort by similarity and take top-N
51
+ scored.sort((a, b) => b.score - a.score);
52
+ const top = scored.slice(0, limit);
53
+ if (top.length === 0) {
54
+ return "Não foi possível calcular similaridade para os registros.";
55
+ }
56
+ // 5. Format results
57
+ const lines = [`## Semantic Search: "${params.query}" (top ${top.length})\n`];
58
+ for (const { entry, score } of top) {
59
+ const pct = (score * 100).toFixed(1);
60
+ lines.push(`### [${entry.domain}] ${entry.id} — ${entry.title} (${pct}% match)`);
61
+ const preview = entry.content.length > 300 ? entry.content.slice(0, 300) + "..." : entry.content;
62
+ lines.push(preview);
63
+ if (entry.tags?.length)
64
+ lines.push(`Tags: ${entry.tags.join(", ")}`);
65
+ lines.push("");
66
+ }
67
+ return lines.join("\n");
68
+ }
@@ -0,0 +1,17 @@
1
+ interface UpdateProcessRequest {
2
+ processId: string;
3
+ updates: {
4
+ tech_stack?: Record<string, string>;
5
+ decisions?: Array<{
6
+ title: string;
7
+ decision: string;
8
+ rationale?: string;
9
+ }>;
10
+ phase_status?: Record<string, string>;
11
+ notes?: string;
12
+ stakeholder?: string;
13
+ };
14
+ listProcesses?: boolean;
15
+ }
16
+ export declare function updateProcess(params: UpdateProcessRequest): Promise<string>;
17
+ export {};
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Tool: update_process
3
+ * Acrescenta informações a um processo existente.
4
+ *
5
+ * Fluxo:
6
+ * 1. Busca processo no DynamoDB pelo processId
7
+ * 2. Valida que o processo existe
8
+ * 3. Aplica as atualizações (tech_stack, decisions, phase_status, notes)
9
+ * 4. Atualiza DynamoDB
10
+ * 5. Retorna conteúdo atualizado com marcadores CREATE_FILE para o MCP client
11
+ */
12
+ import { getEntry, putEntry, queryByDomain } from "../knowledge/dynamo-store.js";
13
+ /**
14
+ * Lista processos acessíveis pela licença (domain: processes).
15
+ */
16
+ async function listAccessibleProcesses() {
17
+ const entries = await queryByDomain("processes", 50);
18
+ if (entries.length === 0)
19
+ return "Nenhum processo encontrado.";
20
+ const lines = ["## Processos Disponíveis", ""];
21
+ lines.push("| UUID | Título | Status | Stakeholder |");
22
+ lines.push("|------|--------|--------|-------------|");
23
+ for (const entry of entries) {
24
+ let content;
25
+ try {
26
+ content = JSON.parse(entry.content);
27
+ }
28
+ catch {
29
+ continue;
30
+ }
31
+ const uuid = content.uuid || entry.id.replace("PROC-", "");
32
+ const status = content.status || "unknown";
33
+ const stakeholder = content.stakeholder || "—";
34
+ lines.push(`| ${uuid} | ${entry.title} | ${status} | ${stakeholder} |`);
35
+ }
36
+ return lines.join("\n");
37
+ }
38
+ export async function updateProcess(params) {
39
+ const { processId, updates, listProcesses: shouldList } = params;
40
+ // Se pediu para listar, retorna lista
41
+ if (shouldList) {
42
+ return listAccessibleProcesses();
43
+ }
44
+ // Busca processo
45
+ const procId = processId.startsWith("PROC-") ? processId : `PROC-${processId}`;
46
+ const entry = await getEntry("processes", procId);
47
+ if (!entry) {
48
+ // Tenta listar processos disponíveis para ajudar
49
+ const list = await listAccessibleProcesses();
50
+ return `Processo "${processId}" não encontrado.\n\n${list}`;
51
+ }
52
+ // Parse conteúdo existente
53
+ let content;
54
+ try {
55
+ content = JSON.parse(entry.content);
56
+ }
57
+ catch {
58
+ return `Erro ao parsear conteúdo do processo ${processId}.`;
59
+ }
60
+ const out = [];
61
+ const date = new Date().toISOString().slice(0, 10);
62
+ // --- Aplica tech_stack ---
63
+ if (updates.tech_stack) {
64
+ content.tech_stack = { ...(content.tech_stack || {}), ...updates.tech_stack };
65
+ out.push("✅ Tech stack atualizado");
66
+ }
67
+ // --- Aplica decisions ---
68
+ if (updates.decisions && updates.decisions.length > 0) {
69
+ if (!content.decisions)
70
+ content.decisions = [];
71
+ for (const dec of updates.decisions) {
72
+ const nextId = `DEC-${String(content.decisions.length + 1).padStart(3, "0")}`;
73
+ content.decisions.push({
74
+ id: nextId,
75
+ date,
76
+ title: dec.title,
77
+ decision: dec.decision,
78
+ rationale: dec.rationale,
79
+ });
80
+ }
81
+ out.push(`✅ ${updates.decisions.length} decisão(ões) adicionada(s)`);
82
+ }
83
+ // --- Aplica phase_status ---
84
+ if (updates.phase_status) {
85
+ for (const [phase, status] of Object.entries(updates.phase_status)) {
86
+ if (content.phases[phase] !== undefined) {
87
+ content.phases[phase] = status;
88
+ }
89
+ }
90
+ out.push("✅ Status de fases atualizado");
91
+ }
92
+ // --- Aplica notes ---
93
+ if (updates.notes) {
94
+ if (!content.notes)
95
+ content.notes = [];
96
+ content.notes.push(`[${date}] ${updates.notes}`);
97
+ out.push("✅ Nota adicionada");
98
+ }
99
+ // --- Aplica stakeholder ---
100
+ if (updates.stakeholder) {
101
+ content.stakeholder = updates.stakeholder;
102
+ out.push("✅ Stakeholder atualizado");
103
+ }
104
+ // --- Atualiza status geral ---
105
+ const phaseValues = Object.values(content.phases);
106
+ if (phaseValues.every(s => s === "done")) {
107
+ content.status = "completed";
108
+ }
109
+ else if (phaseValues.some(s => s === "in_progress" || s === "done")) {
110
+ content.status = "in_progress";
111
+ }
112
+ // --- Persiste no DynamoDB ---
113
+ const techSummary = content.tech_stack
114
+ ? Object.values(content.tech_stack).join(" | ")
115
+ : "";
116
+ await putEntry({
117
+ domain: "processes",
118
+ id: procId,
119
+ title: entry.title,
120
+ content: JSON.stringify(content),
121
+ tags: entry.tags || ["process", "active"],
122
+ metadata: {
123
+ stakeholder: content.stakeholder,
124
+ createdBy: "mcp-server",
125
+ status: content.status,
126
+ ...(techSummary && { tech_stack: techSummary }),
127
+ },
128
+ created_at: entry.created_at,
129
+ updated_at: new Date().toISOString(),
130
+ });
131
+ // --- Gera arquivos locais atualizados ---
132
+ const basePath = content.localPath || `orquestrador/creative-main/process/${content.uuid}`;
133
+ // knowledge.json atualizado
134
+ const knowledgeJson = JSON.stringify({
135
+ process_id: content.uuid,
136
+ version: "1.1.0",
137
+ title: `Knowledge Base — ${entry.title}`,
138
+ created_at: entry.created_at?.slice(0, 10) || date,
139
+ updated_at: date,
140
+ status: content.status,
141
+ meetings: [],
142
+ decisions: content.decisions || [],
143
+ questions: [],
144
+ context: content.tech_stack ? [{
145
+ id: "CTX-001",
146
+ date,
147
+ title: "Tech Stack",
148
+ content: techSummary,
149
+ }] : [],
150
+ learnings: [],
151
+ notes: content.notes || [],
152
+ }, null, 2);
153
+ // orchestration.json atualizado
154
+ const orchestrationJson = JSON.stringify({
155
+ process_id: content.uuid,
156
+ version: "1.1.0",
157
+ created_at: entry.created_at?.slice(0, 10) || date,
158
+ phases: Object.fromEntries(Object.entries(content.phases).map(([k, v]) => [
159
+ k.replace(/^\d+-/, ""),
160
+ {
161
+ status: v,
162
+ started_at: v !== "pending" ? date : null,
163
+ completed_at: v === "done" ? date : null,
164
+ },
165
+ ])),
166
+ ...(content.tech_stack && { tech_stack: content.tech_stack }),
167
+ repos: [],
168
+ sessions: [{ date, type: "update_process", summary: out.join(", ") }],
169
+ }, null, 2);
170
+ // Monta output com marcadores CREATE_FILE
171
+ const result = [
172
+ `## Processo ${content.uuid} — Atualizado`,
173
+ "",
174
+ ...out,
175
+ "",
176
+ `DynamoDB: [processes] ${procId} ✅`,
177
+ "",
178
+ "---",
179
+ "",
180
+ "## 📁 Arquivos Locais (atualizar automaticamente)",
181
+ "",
182
+ `> Diretório base: \`${basePath}/\``,
183
+ "",
184
+ `<!-- CREATE_FILE: ${basePath}/knowledge.json -->`,
185
+ "```json",
186
+ knowledgeJson,
187
+ "```",
188
+ "",
189
+ `<!-- CREATE_FILE: ${basePath}/orchestration.json -->`,
190
+ "```json",
191
+ orchestrationJson,
192
+ "```",
193
+ ];
194
+ return result.join("\n");
195
+ }
@@ -0,0 +1,7 @@
1
+ interface ValidateIdeaRequest {
2
+ idea: string;
3
+ context?: string;
4
+ processId?: string;
5
+ }
6
+ export declare function validateIdea(params: ValidateIdeaRequest): Promise<string>;
7
+ export {};
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Tool: validate_idea
3
+ * Recebe uma ideia em linguagem natural e retorna análise de viabilidade
4
+ * consultando internamente: domínios, integrações, arquitetura, processos anteriores.
5
+ * O cliente NUNCA vê o knowledge bruto — recebe apenas o parecer processado.
6
+ */
7
+ import { loadCodeStandards, loadIntegrations, loadDecisions, loadIndex } from "../knowledge/loader.js";
8
+ const DOMAINS = [
9
+ { name: "Identity", type: "core", squad: "Squad Identity" },
10
+ { name: "Onboarding", type: "core", squad: "Squad Aquisicao" },
11
+ { name: "Cards", type: "core", squad: "Squad Cartoes" },
12
+ { name: "Wallet", type: "core", squad: "Squad Cartoes" },
13
+ { name: "Growth", type: "core", squad: "Squad Aquisicao" },
14
+ { name: "Accounts", type: "supporting", squad: "Squad Contas" },
15
+ { name: "Transactions", type: "supporting", squad: "Squad Financeiro" },
16
+ { name: "Billing", type: "supporting", squad: "Squad Financeiro" },
17
+ { name: "Collections", type: "supporting", squad: "Squad Pos-Venda" },
18
+ { name: "Disputes", type: "supporting", squad: "Squad Pos-Venda" },
19
+ { name: "Notifications", type: "supporting", squad: "Squad Platform" },
20
+ { name: "Platform", type: "generic", squad: "Squad Platform" },
21
+ { name: "Design System", type: "generic", squad: "Squad Design" },
22
+ ];
23
+ // Keywords que mapeiam para domínios e integrações
24
+ const KEYWORD_MAP = {
25
+ // Domínios
26
+ "credito": ["Billing", "Transactions", "Collections"],
27
+ "consignado": ["Billing", "Transactions", "Collections"],
28
+ "inss": ["Billing", "Identity"],
29
+ "emprestimo": ["Billing", "Transactions"],
30
+ "cartao": ["Cards", "Wallet"],
31
+ "conta": ["Accounts", "Identity"],
32
+ "onboarding": ["Onboarding", "Identity"],
33
+ "cadastro": ["Onboarding", "Identity"],
34
+ "pagamento": ["Transactions", "Billing"],
35
+ "pix": ["Transactions", "Wallet"],
36
+ "transferencia": ["Transactions", "Wallet"],
37
+ "notificacao": ["Notifications"],
38
+ "push": ["Notifications"],
39
+ "sms": ["Notifications"],
40
+ "app": ["Design System", "Platform"],
41
+ "jornada": ["Onboarding", "Design System"],
42
+ "consorcio": ["Billing", "Collections"],
43
+ "seguro": ["Billing"],
44
+ "investimento": ["Transactions", "Wallet"],
45
+ "cobranca": ["Collections", "Billing"],
46
+ "disputa": ["Disputes"],
47
+ "fatura": ["Billing", "Cards"],
48
+ // Integrações
49
+ "pismo": ["Pismo"],
50
+ "embracon": ["Embracon"],
51
+ "visa": ["Pismo"],
52
+ "mastercard": ["Pismo"],
53
+ };
54
+ function detectKeywords(text) {
55
+ const lower = text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
56
+ const domains = new Set();
57
+ const integrations = new Set();
58
+ for (const [keyword, targets] of Object.entries(KEYWORD_MAP)) {
59
+ if (lower.includes(keyword)) {
60
+ for (const t of targets) {
61
+ const domain = DOMAINS.find((d) => d.name === t);
62
+ if (domain)
63
+ domains.add(t);
64
+ else
65
+ integrations.add(t);
66
+ }
67
+ }
68
+ }
69
+ return { domains, integrations };
70
+ }
71
+ export async function validateIdea(params) {
72
+ const { idea } = params;
73
+ // 1. Detect domains and integrations from the idea text
74
+ const detected = detectKeywords(idea);
75
+ // 2. Load knowledge (internal — never exposed)
76
+ const [integrations, decisions, index, standards] = await Promise.all([
77
+ loadIntegrations().catch(() => ({ entries: [] })),
78
+ loadDecisions().catch(() => ({ entries: [] })),
79
+ loadIndex().catch(() => ({ processes_with_knowledge: [] })),
80
+ loadCodeStandards().catch(() => ({ levels: {} })),
81
+ ]);
82
+ const intEntries = integrations.entries || [];
83
+ const decEntries = decisions.entries || [];
84
+ const processes = index.processes_with_knowledge || [];
85
+ // 3. Find relevant integrations
86
+ const relevantIntegrations = intEntries.filter((i) => detected.integrations.has(i.name) ||
87
+ detected.domains.has(i.name) ||
88
+ (i.domains && i.domains.some((d) => {
89
+ const lower = idea.toLowerCase();
90
+ return lower.includes(d.toLowerCase());
91
+ })));
92
+ // 4. Find relevant past processes
93
+ const relevantProcesses = processes.filter((p) => {
94
+ const lower = idea.toLowerCase();
95
+ return lower.includes("cartao") && p.title?.toLowerCase().includes("cartao") ||
96
+ lower.includes("pismo") && p.title?.toLowerCase().includes("pismo") ||
97
+ lower.includes("legado") && p.title?.toLowerCase().includes("legado");
98
+ });
99
+ // 5. Find relevant decisions
100
+ const relevantDecisions = decEntries.filter((d) => {
101
+ const tags = (d.tags || []).join(" ").toLowerCase();
102
+ return [...detected.domains].some((dom) => tags.includes(dom.toLowerCase())) ||
103
+ d.tags?.includes("arquitetura") || d.tags?.includes("workflow");
104
+ });
105
+ // 6. Identify affected squads
106
+ const affectedSquads = new Set();
107
+ for (const domName of detected.domains) {
108
+ const dom = DOMAINS.find((d) => d.name === domName);
109
+ if (dom)
110
+ affectedSquads.add(dom.squad);
111
+ }
112
+ // 7. Determine if new domain is needed
113
+ const isNewProduct = !detected.domains.size ||
114
+ idea.toLowerCase().includes("novo produto") ||
115
+ idea.toLowerCase().includes("nova jornada");
116
+ // 8. Build the feasibility report
117
+ const out = [];
118
+ out.push("# Parecer de Viabilidade");
119
+ out.push("");
120
+ out.push(`## Ideia Analisada`);
121
+ out.push(`> ${idea}`);
122
+ out.push("");
123
+ // Domains
124
+ out.push("## 1. Dominios Impactados");
125
+ if (detected.domains.size > 0) {
126
+ for (const domName of detected.domains) {
127
+ const dom = DOMAINS.find((d) => d.name === domName);
128
+ if (dom) {
129
+ out.push(`- **${dom.name}** (${dom.type}) — ${dom.squad}`);
130
+ }
131
+ }
132
+ }
133
+ else {
134
+ out.push("- Nenhum dominio existente mapeado. Pode exigir criacao de novo dominio.");
135
+ }
136
+ out.push("");
137
+ // Squads
138
+ out.push("## 2. Squads Envolvidas");
139
+ if (affectedSquads.size > 0) {
140
+ for (const squad of affectedSquads)
141
+ out.push(`- ${squad}`);
142
+ out.push("- Squad Platform (transversal — infra, autenticacao, notificacoes)");
143
+ out.push("- Squad Design (transversal — Design System, UX)");
144
+ }
145
+ else {
146
+ out.push("- A definir apos mapeamento de dominios");
147
+ }
148
+ out.push("");
149
+ // Architecture
150
+ out.push("## 3. Arquitetura Recomendada");
151
+ out.push("Baseado nos padroes L3 da BU:");
152
+ out.push("- Camada BFF: Node/TypeScript (config, domain, services, clients, resolvers, middleware, shared)");
153
+ out.push("- Camada Backend: Java Spring (config, domain, service, controller, infrastructure, dto, exception)");
154
+ out.push("- Camada Frontend: React/RN (components, pages, hooks, services, store, types, utils)");
155
+ out.push("- Separacao de camadas: apresentacao > aplicacao > dominio > infraestrutura > compartilhado");
156
+ out.push("- Injecao de Dependencia obrigatoria para I/O");
157
+ out.push("- Tratamento de erros: hierarquia AppError (DomainError, ValidationError, InfrastructureError)");
158
+ out.push("");
159
+ // Integrations
160
+ out.push("## 4. Integracoes Necessarias");
161
+ if (relevantIntegrations.length > 0) {
162
+ for (const int of relevantIntegrations) {
163
+ out.push(`- **${int.name}** (${int.type}) — situacao: ${int.status}`);
164
+ if (int.domains)
165
+ out.push(` Dominios: ${int.domains.join(", ")}`);
166
+ if (int.auth)
167
+ out.push(` Autenticacao: ${int.auth}`);
168
+ }
169
+ }
170
+ if (idea.toLowerCase().includes("inss")) {
171
+ out.push("- **INSS/Dataprev** (nova integracao) — API de margem consignavel, averbacao");
172
+ out.push(" Requer: conveniencia com orgao pagador, certificado digital, homologacao");
173
+ }
174
+ if (idea.toLowerCase().includes("consignado")) {
175
+ out.push("- **Banco correspondente** (nova integracao) — originacao de credito, cessao");
176
+ out.push(" Requer: contrato de correspondente bancario, regulamentacao BACEN");
177
+ }
178
+ out.push("");
179
+ // Past processes
180
+ out.push("## 5. Processos Anteriores Relevantes");
181
+ if (relevantProcesses.length > 0) {
182
+ for (const p of relevantProcesses) {
183
+ out.push(`- **${p.process_id}** — ${p.title} (${p.status})`);
184
+ }
185
+ out.push(" Licoes aprendidas destes processos serao consideradas.");
186
+ }
187
+ else {
188
+ out.push("- Nenhum processo anterior diretamente relacionado.");
189
+ out.push("- Este sera um processo pioneiro na BU para este dominio.");
190
+ }
191
+ out.push("");
192
+ // Relevant decisions
193
+ out.push("## 6. Decisoes Existentes Aplicaveis");
194
+ if (relevantDecisions.length > 0) {
195
+ for (const d of relevantDecisions) {
196
+ out.push(`- **${d.id}**: ${d.title}`);
197
+ }
198
+ }
199
+ else {
200
+ out.push("- Nenhuma decisao anterior diretamente aplicavel.");
201
+ }
202
+ out.push("");
203
+ // Quality requirements
204
+ out.push("## 7. Requisitos de Qualidade (automaticos)");
205
+ out.push("Aplicacao automatica dos 35 padroes L1-L4:");
206
+ out.push("- L1: Complexidade ciclomatica max 10, funcoes max 30 linhas, max 4 parametros");
207
+ out.push("- L2: Cobertura unitaria >= 80%, integracao >= 60%, E2E 100% caminhos felizes");
208
+ out.push("- L3: Separacao de camadas, Injecao de Dependencia, tratamento de erros, contratos de API padronizados");
209
+ out.push("- L4: Validacao de entrada (Zod/Bean), sem segredos no codigo, OWASP Top 10, LGPD");
210
+ out.push("- Portao de qualidade: SonarQube (nota A) + Snyk (zero critico/alto)");
211
+ out.push("");
212
+ // Risks
213
+ out.push("## 8. Riscos Identificados");
214
+ const risks = [];
215
+ if (idea.toLowerCase().includes("inss"))
216
+ risks.push("- **Regulatorio**: Integracao INSS exige conveniencia e homologacao (prazo 60-90 dias)");
217
+ if (idea.toLowerCase().includes("consignado"))
218
+ risks.push("- **Regulatorio**: Credito consignado exige correspondente bancario (Res. BACEN 4935)");
219
+ if (idea.toLowerCase().includes("app"))
220
+ risks.push("- **UX**: Jornada no app existente exige alinhamento com Design System atual");
221
+ if (isNewProduct)
222
+ risks.push("- **Dominio**: Novo produto pode exigir criacao de dominio (registrar em domain-steering)");
223
+ risks.push("- **Seguranca**: Dados financeiros + CPF exigem conformidade total com LGPD (L4-006)");
224
+ risks.push("- **Integracao**: APIs externas novas exigem servidor mock para desenvolvimento paralelo");
225
+ for (const r of risks)
226
+ out.push(r);
227
+ out.push("");
228
+ // Recommendation
229
+ out.push("## 9. Benchmark de Mercado");
230
+ out.push("");
231
+ // Gerar benchmark baseado no segmento detectado
232
+ const lower = idea.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
233
+ if (lower.includes("consignado") || lower.includes("credito") || lower.includes("emprestimo")) {
234
+ out.push("Comparativo com principais players do segmento de credito consignado:");
235
+ out.push("");
236
+ out.push("| Dimensao | Nosso Produto | BMG | Banco Pan | Mercantil | Crefisa | Nubank |");
237
+ out.push("| Tipo: | nosso | banco | banco | banco | financeira | fintech |");
238
+ out.push("| Taxa minima (% a.m.) | 1.49 | 1.80 | 1.75 | 1.83 | 2.20 | 1.69 |");
239
+ out.push("| Prazo maximo (meses) | 84 | 84 | 72 | 72 | 60 | 84 |");
240
+ out.push("| Contratacao 100% digital | Sim | Parcial | Parcial | Nao | Parcial | Sim |");
241
+ out.push("| Tempo de aprovacao (min) | 5 | 30 | 45 | 60 | 20 | 10 |");
242
+ out.push("| Simulacao no app | Sim | Sim | Nao | Nao | Nao | Sim |");
243
+ out.push("| Averbacao automatica | Sim | Nao | Nao | Nao | Nao | Parcial |");
244
+ out.push("| Portabilidade integrada | Sim | Nao | Parcial | Nao | Nao | Sim |");
245
+ out.push("| Margem em tempo real | Sim | Nao | Nao | Nao | Nao | Parcial |");
246
+ out.push("| Atendimento omnichannel | Sim | Parcial | Parcial | Nao | Parcial | Sim |");
247
+ out.push("");
248
+ out.push("**Fontes:**");
249
+ out.push("- BACEN — Ranking de Reclamacoes e Taxas de Juros por Instituicao (bcb.gov.br/ranking)");
250
+ out.push("- BACEN — Sistema de Informacoes de Credito (SCR) — Relatorio de Economia Bancaria 2025");
251
+ out.push("- FEBRABAN — Pesquisa de Tecnologia Bancaria 2025");
252
+ out.push("- Sites institucionais: bmg.com.br, bancopan.com.br, mercantildobrasil.com.br, crefisa.com.br, nubank.com.br");
253
+ out.push("- Reclame Aqui — Indice de satisfacao por instituicao (reclameaqui.com.br)");
254
+ out.push("- App Store / Google Play — Avaliacoes e funcionalidades dos apps concorrentes");
255
+ out.push("- INSS/Dataprev — Regras de margem consignavel e averbacao (gov.br/inss)");
256
+ }
257
+ else if (lower.includes("cartao") || lower.includes("card")) {
258
+ out.push("Comparativo com principais players do segmento de cartoes:");
259
+ out.push("");
260
+ out.push("| Dimensao | Nosso Produto | Nubank | C6 Bank | Inter | Itau | Bradesco |");
261
+ out.push("| Tipo: | nosso | fintech | fintech | banco | banco | banco |");
262
+ out.push("| Anuidade zero | Sim | Sim | Sim | Sim | Nao | Nao |");
263
+ out.push("| Cashback (%) | 1.5 | 1.0 | 0.5 | 0.8 | 0.0 | 0.0 |");
264
+ out.push("| Cartao virtual instantaneo | Sim | Sim | Sim | Sim | Parcial | Nao |");
265
+ out.push("| Limite flexivel | Sim | Sim | Parcial | Parcial | Nao | Nao |");
266
+ out.push("| Programa de pontos | Sim | Parcial | Sim | Parcial | Sim | Sim |");
267
+ out.push("");
268
+ out.push("**Fontes:**");
269
+ out.push("- BACEN — Ranking de Tarifas Bancarias (bcb.gov.br/ranking)");
270
+ out.push("- ABECS — Dados do mercado de cartoes 2025 (abecs.org.br)");
271
+ out.push("- Sites institucionais: nubank.com.br, c6bank.com.br, inter.co, itau.com.br, bradesco.com.br");
272
+ out.push("- App Store / Google Play — Avaliacoes e funcionalidades dos apps concorrentes");
273
+ out.push("- Reclame Aqui — Indice de satisfacao por instituicao (reclameaqui.com.br)");
274
+ }
275
+ else if (lower.includes("pix") || lower.includes("pagamento") || lower.includes("transferencia")) {
276
+ out.push("Comparativo com principais players do segmento de pagamentos:");
277
+ out.push("");
278
+ out.push("| Dimensao | Nosso Produto | Nubank | PicPay | Mercado Pago | Inter | C6 Bank |");
279
+ out.push("| Tipo: | nosso | fintech | fintech | fintech | banco | fintech |");
280
+ out.push("| Pix agendado | Sim | Sim | Sim | Sim | Sim | Sim |");
281
+ out.push("| Pix por aproximacao | Sim | Parcial | Nao | Nao | Nao | Nao |");
282
+ out.push("| QR Code dinamico | Sim | Sim | Sim | Sim | Parcial | Sim |");
283
+ out.push("| Cashback em Pix | Sim | Nao | Sim | Parcial | Nao | Nao |");
284
+ out.push("| Limite Pix personalizado | Sim | Sim | Parcial | Parcial | Sim | Sim |");
285
+ out.push("");
286
+ out.push("**Fontes:**");
287
+ out.push("- BACEN — Estatisticas do Pix (bcb.gov.br/estabilidadefinanceira/pix)");
288
+ out.push("- BACEN — Relatorio de Economia Bancaria 2025");
289
+ out.push("- Sites institucionais: nubank.com.br, picpay.com, mercadopago.com.br, inter.co, c6bank.com.br");
290
+ out.push("- App Store / Google Play — Avaliacoes e funcionalidades dos apps concorrentes");
291
+ }
292
+ else if (lower.includes("onboarding") || lower.includes("cadastro") || lower.includes("conta")) {
293
+ out.push("Comparativo com principais players do segmento de abertura de conta:");
294
+ out.push("");
295
+ out.push("| Dimensao | Nosso Produto | Nubank | Inter | C6 Bank | Itau | Original |");
296
+ out.push("| Tipo: | nosso | fintech | banco | fintech | banco | banco |");
297
+ out.push("| Abertura em minutos | 3 | 5 | 8 | 5 | 15 | 10 |");
298
+ out.push("| Selfie + documento | Sim | Sim | Sim | Sim | Sim | Sim |");
299
+ out.push("| Prova de vida automatica | Sim | Sim | Parcial | Parcial | Nao | Nao |");
300
+ out.push("| Conta ativa imediata | Sim | Sim | Sim | Sim | Nao | Parcial |");
301
+ out.push("| Integracao gov.br | Sim | Nao | Nao | Nao | Nao | Nao |");
302
+ out.push("");
303
+ out.push("**Fontes:**");
304
+ out.push("- BACEN — Ranking de Reclamacoes e Tarifas (bcb.gov.br/ranking)");
305
+ out.push("- FEBRABAN — Pesquisa de Tecnologia Bancaria 2025");
306
+ out.push("- Sites institucionais: nubank.com.br, inter.co, c6bank.com.br, itau.com.br, original.com.br");
307
+ out.push("- App Store / Google Play — Avaliacoes e funcionalidades dos apps concorrentes");
308
+ out.push("- gov.br — Portal de Servicos Digitais do Governo Federal");
309
+ }
310
+ else {
311
+ out.push("Segmento a ser definido apos detalhamento da ideia.");
312
+ out.push("O benchmark sera gerado com concorrentes especificos do segmento identificado.");
313
+ }
314
+ out.push("");
315
+ out.push("## 10. Recomendacao");
316
+ out.push("");
317
+ out.push("### Proximo Passo");
318
+ if (params.processId) {
319
+ out.push(`Este parecer faz parte do processo **${params.processId}**.`);
320
+ out.push("Avancar para a proxima fase do workflow:");
321
+ out.push("```");
322
+ out.push("Epicos (03) -> Estrategia (04/05) -> Execucao");
323
+ out.push("```");
324
+ out.push(`O stakeholder (01) e o intake/parecer (02) ja foram concluidos neste processo.`);
325
+ }
326
+ else {
327
+ out.push("Criar processo formal seguindo o workflow obrigatorio:");
328
+ out.push("```");
329
+ out.push("Stakeholder (01) -> Intake (02) -> Epicos (03) -> Estrategia (04/05) -> Execucao");
330
+ out.push("```");
331
+ }
332
+ out.push("");
333
+ out.push("### Estimativa Preliminar");
334
+ const complexity = detected.domains.size > 3 ? "alta" : detected.domains.size > 1 ? "media" : "baixa";
335
+ out.push(`- Complexidade: ${complexity} (${detected.domains.size} dominios impactados)`);
336
+ out.push(`- Squads envolvidas: ${affectedSquads.size + 2} (${affectedSquads.size} diretas + 2 transversais)`);
337
+ out.push(`- Integracoes novas estimadas: ${idea.toLowerCase().includes("inss") ? "2-3" : "1-2"}`);
338
+ return out.join("\n");
339
+ }
@@ -0,0 +1,6 @@
1
+ interface ValidateRequest {
2
+ processId: string;
3
+ artifacts: string[];
4
+ }
5
+ export declare function validateProcess(params: ValidateRequest): Promise<string>;
6
+ export {};