@semacode/cli 0.8.8 → 1.0.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 (44) hide show
  1. package/README.md +11 -3
  2. package/dist/drift.d.ts +30 -1
  3. package/dist/drift.js +373 -17
  4. package/dist/drift.js.map +1 -1
  5. package/dist/index.js +828 -53
  6. package/dist/index.js.map +1 -1
  7. package/docs/AGENT_STARTER.md +10 -4
  8. package/docs/como-ensinar-a-sema-para-ia.md +17 -11
  9. package/docs/fluxo-pratico-ia-sema.md +42 -38
  10. package/docs/instalacao-e-primeiro-uso.md +189 -0
  11. package/docs/integracao-com-ia.md +228 -0
  12. package/docs/pagamento-ponta-a-ponta.md +155 -0
  13. package/docs/prompt-base-ia-sema.md +10 -3
  14. package/docs/sintaxe.md +267 -0
  15. package/exemplos/automacao.sema +107 -0
  16. package/exemplos/cadastro_usuario.sema +54 -0
  17. package/exemplos/calculadora.sema +78 -0
  18. package/exemplos/crud_simples.sema +89 -0
  19. package/exemplos/operacao_estrategia.sema +402 -0
  20. package/exemplos/pagamento.sema +222 -0
  21. package/exemplos/pagamento_dominio.sema +35 -0
  22. package/exemplos/testes_embutidos.sema +45 -0
  23. package/exemplos/tratamento_erro.sema +157 -0
  24. package/node_modules/@sema/gerador-dart/package.json +1 -1
  25. package/node_modules/@sema/gerador-python/package.json +1 -1
  26. package/node_modules/@sema/gerador-typescript/package.json +1 -1
  27. package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +14 -1
  28. package/node_modules/@sema/nucleo/dist/formatador/index.js +131 -22
  29. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -1
  30. package/node_modules/@sema/nucleo/dist/ir/conversor.js +546 -102
  31. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -1
  32. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +83 -5
  33. package/node_modules/@sema/nucleo/dist/lexer/lexer.js +1 -1
  34. package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +1 -1
  35. package/node_modules/@sema/nucleo/dist/lexer/tokens.js +10 -0
  36. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -1
  37. package/node_modules/@sema/nucleo/dist/parser/parser.js +230 -19
  38. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -1
  39. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +6 -1
  40. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +269 -10
  41. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -1
  42. package/node_modules/@sema/nucleo/package.json +1 -1
  43. package/node_modules/@sema/padroes/package.json +1 -1
  44. package/package.json +7 -6
@@ -1,13 +1,131 @@
1
1
  import { parsearEfeitoSemantico, parsearEtapaFlow, parsearExpressaoSemantica, parsearTransicaoEstado } from "../semantico/estruturas.js";
2
+ const TIPOS_PRIMITIVOS = new Set([
3
+ "Texto",
4
+ "Numero",
5
+ "Inteiro",
6
+ "Decimal",
7
+ "Booleano",
8
+ "Data",
9
+ "DataHora",
10
+ "Id",
11
+ "Email",
12
+ "Url",
13
+ "Json",
14
+ "Vazio",
15
+ ]);
16
+ function encontrarSubBloco(bloco, palavraChave) {
17
+ return bloco.blocos.find((subbloco) => subbloco.tipo === "bloco_generico" && subbloco.palavraChave === palavraChave);
18
+ }
19
+ function localizarCampo(bloco, ...nomes) {
20
+ return bloco?.campos.find((campo) => nomes.includes(campo.nome));
21
+ }
22
+ function valorCampoCompleto(campo) {
23
+ if (!campo) {
24
+ return undefined;
25
+ }
26
+ return [campo.valor, ...campo.modificadores].join(" ").trim() || undefined;
27
+ }
28
+ function normalizarTipoDeclarado(tipo) {
29
+ return tipo
30
+ .replace(/\s*([<>\[\](),|?])\s*/g, "$1")
31
+ .replace(/\s+/g, "")
32
+ .trim();
33
+ }
34
+ function dividirNoNivelRaiz(texto, separador) {
35
+ const partes = [];
36
+ let profundidadeAngular = 0;
37
+ let profundidadeColchete = 0;
38
+ let inicio = 0;
39
+ for (let indice = 0; indice < texto.length; indice += 1) {
40
+ const caractere = texto[indice];
41
+ if (caractere === "<") {
42
+ profundidadeAngular += 1;
43
+ continue;
44
+ }
45
+ if (caractere === ">") {
46
+ profundidadeAngular = Math.max(0, profundidadeAngular - 1);
47
+ continue;
48
+ }
49
+ if (caractere === "[") {
50
+ profundidadeColchete += 1;
51
+ continue;
52
+ }
53
+ if (caractere === "]") {
54
+ profundidadeColchete = Math.max(0, profundidadeColchete - 1);
55
+ continue;
56
+ }
57
+ if (profundidadeAngular === 0 && profundidadeColchete === 0 && texto.startsWith(separador, indice)) {
58
+ partes.push(texto.slice(inicio, indice));
59
+ inicio = indice + separador.length;
60
+ indice += separador.length - 1;
61
+ }
62
+ }
63
+ partes.push(texto.slice(inicio));
64
+ return partes.map((parte) => parte.trim()).filter(Boolean);
65
+ }
66
+ function analisarCampoTipo(tipo, modificadores) {
67
+ const tipoOriginal = normalizarTipoDeclarado(tipo);
68
+ const modificadoresNormalizados = modificadores.map((item) => item.trim()).filter(Boolean);
69
+ const refinamentos = modificadoresNormalizados.filter((item) => !["required", "optional", "opcional"].includes(item));
70
+ const opcionalPorModificador = modificadoresNormalizados.includes("optional") || modificadoresNormalizados.includes("opcional");
71
+ let tipoBase = tipoOriginal;
72
+ let cardinalidade = "unitario";
73
+ let tiposAlternativos = [];
74
+ let tipoItem;
75
+ let chaveMapa;
76
+ let valorMapa;
77
+ let opcional = opcionalPorModificador;
78
+ if (tipoBase.endsWith("?")) {
79
+ opcional = true;
80
+ tipoBase = tipoBase.slice(0, -1);
81
+ }
82
+ if (/^Opcional<.+>$/.test(tipoBase)) {
83
+ opcional = true;
84
+ tipoBase = tipoBase.slice("Opcional<".length, -1);
85
+ }
86
+ const uniao = dividirNoNivelRaiz(tipoBase, "|");
87
+ if (uniao.length > 1) {
88
+ cardinalidade = "uniao";
89
+ tiposAlternativos = uniao.map(normalizarTipoDeclarado);
90
+ tipoBase = tiposAlternativos[0] ?? tipoBase;
91
+ }
92
+ else if (/^Lista<.+>$/.test(tipoBase)) {
93
+ cardinalidade = "lista";
94
+ tipoItem = tipoBase.slice("Lista<".length, -1).trim();
95
+ tipoBase = tipoItem;
96
+ }
97
+ else if (/^Mapa<.+>$/.test(tipoBase)) {
98
+ cardinalidade = "mapa";
99
+ const partesMapa = dividirNoNivelRaiz(tipoBase.slice("Mapa<".length, -1), ",");
100
+ chaveMapa = partesMapa[0];
101
+ valorMapa = partesMapa[1];
102
+ tipoBase = valorMapa ?? tipoBase;
103
+ }
104
+ return {
105
+ tipo: tipoOriginal,
106
+ modificadores: modificadoresNormalizados,
107
+ tipoOriginal,
108
+ tipoBase,
109
+ cardinalidade,
110
+ opcional,
111
+ tiposAlternativos,
112
+ tipoItem,
113
+ chaveMapa,
114
+ valorMapa,
115
+ refinamentos,
116
+ };
117
+ }
118
+ function converterCampo(campo) {
119
+ return {
120
+ nome: campo.nome,
121
+ ...analisarCampoTipo(campo.valor, campo.modificadores),
122
+ };
123
+ }
2
124
  function converterCampos(bloco) {
3
125
  if (!bloco) {
4
126
  return [];
5
127
  }
6
- return bloco.campos.map((campo) => ({
7
- nome: campo.nome,
8
- tipo: campo.valor,
9
- modificadores: campo.modificadores,
10
- }));
128
+ return bloco.campos.map(converterCampo);
11
129
  }
12
130
  function converterBloco(bloco) {
13
131
  return {
@@ -30,29 +148,276 @@ function converterCaso(caso) {
30
148
  error: caso.error ? converterBloco(caso.error) : undefined,
31
149
  };
32
150
  }
33
- function encontrarSubBloco(bloco, palavraChave) {
34
- return bloco.blocos.find((subbloco) => subbloco.tipo === "bloco_generico" && subbloco.palavraChave === palavraChave);
151
+ function converterImplementacoes(bloco) {
152
+ const implementacoes = [];
153
+ for (const campo of bloco?.campos ?? []) {
154
+ const origem = campo.nome.toLowerCase();
155
+ if (origem === "ts" || origem === "typescript") {
156
+ implementacoes.push({ origem: "ts", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
157
+ continue;
158
+ }
159
+ if (origem === "py" || origem === "python") {
160
+ implementacoes.push({ origem: "py", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
161
+ continue;
162
+ }
163
+ if (origem === "dart") {
164
+ implementacoes.push({ origem: "dart", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
165
+ continue;
166
+ }
167
+ if (origem === "cs" || origem === "csharp" || origem === "dotnet") {
168
+ implementacoes.push({ origem: "cs", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
169
+ continue;
170
+ }
171
+ if (origem === "java") {
172
+ implementacoes.push({ origem: "java", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
173
+ continue;
174
+ }
175
+ if (origem === "go" || origem === "golang") {
176
+ implementacoes.push({ origem: "go", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
177
+ continue;
178
+ }
179
+ if (origem === "rust" || origem === "rs") {
180
+ implementacoes.push({ origem: "rust", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
181
+ continue;
182
+ }
183
+ if (origem === "cpp" || origem === "cxx" || origem === "cc" || origem === "c++") {
184
+ implementacoes.push({ origem: "cpp", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
185
+ }
186
+ }
187
+ return implementacoes;
35
188
  }
36
- function converterErrosPublicos(bloco) {
37
- return (bloco?.campos ?? []).map((campo) => ({
38
- nome: campo.nome,
39
- codigo: campo.nome,
40
- mensagem: [campo.valor, ...campo.modificadores].join(" ").trim() || undefined,
189
+ function converterVinculos(bloco) {
190
+ if (!bloco) {
191
+ return [];
192
+ }
193
+ const campos = bloco.campos.map((campo) => {
194
+ const valor = valorCampoCompleto(campo) ?? "";
195
+ return {
196
+ tipo: campo.nome,
197
+ valor,
198
+ arquivo: campo.nome === "arquivo" ? valor : undefined,
199
+ simbolo: campo.nome === "simbolo" ? valor : undefined,
200
+ recurso: ["recurso", "tabela", "fila", "cache", "storage"].includes(campo.nome) ? valor : undefined,
201
+ superficie: ["superficie", "rota", "worker", "cron", "webhook", "evento", "policy", "fila", "cache", "storage"].includes(campo.nome) ? valor : undefined,
202
+ statusResolucao: "nao_verificado",
203
+ };
204
+ });
205
+ const linhas = bloco.linhas.map((linha) => {
206
+ const [tipo, ...resto] = linha.conteudo.split(/\s+/);
207
+ const valor = resto.join(" ").trim();
208
+ return {
209
+ tipo: tipo ?? "desconhecido",
210
+ valor,
211
+ statusResolucao: "nao_verificado",
212
+ };
213
+ }).filter((item) => item.valor);
214
+ const subblocos = bloco.blocos
215
+ .filter((item) => item.tipo === "bloco_generico")
216
+ .map((item) => ({
217
+ tipo: item.palavraChave === "desconhecido" ? (item.nome ?? "desconhecido") : item.palavraChave,
218
+ valor: item.nome ?? item.palavraChave,
219
+ arquivo: valorCampoCompleto(localizarCampo(item, "arquivo")),
220
+ simbolo: valorCampoCompleto(localizarCampo(item, "simbolo")),
221
+ recurso: valorCampoCompleto(localizarCampo(item, "recurso", "tabela", "fila", "cache", "storage")),
222
+ superficie: valorCampoCompleto(localizarCampo(item, "superficie", "rota", "worker", "cron", "webhook", "evento")),
223
+ statusResolucao: "nao_verificado",
41
224
  }));
225
+ return [...campos, ...linhas, ...subblocos];
42
226
  }
43
- function recomporCaminho(campo) {
44
- if (!campo) {
45
- return undefined;
227
+ function converterExecucao(bloco) {
228
+ const idempotencia = valorCampoCompleto(localizarCampo(bloco, "idempotencia"));
229
+ const criticidadeOperacional = valorCampoCompleto(localizarCampo(bloco, "criticidade_operacional"));
230
+ return {
231
+ idempotencia: idempotencia === "verdadeiro" || idempotencia === "true",
232
+ timeout: valorCampoCompleto(localizarCampo(bloco, "timeout")) ?? "padrao",
233
+ retry: valorCampoCompleto(localizarCampo(bloco, "retry")) ?? "nenhum",
234
+ compensacao: valorCampoCompleto(localizarCampo(bloco, "compensacao")) ?? "nenhuma",
235
+ criticidadeOperacional: (criticidadeOperacional === "baixa"
236
+ || criticidadeOperacional === "alta"
237
+ || criticidadeOperacional === "critica") ? criticidadeOperacional : "media",
238
+ explicita: Boolean(bloco),
239
+ };
240
+ }
241
+ function converterErrosTask(bloco, fallback) {
242
+ const erros = new Map();
243
+ for (const campo of bloco?.campos ?? []) {
244
+ erros.set(campo.nome, {
245
+ codigo: campo.nome,
246
+ mensagem: valorCampoCompleto(campo) ?? "",
247
+ });
46
248
  }
47
- return [campo.valor, ...campo.modificadores]
48
- .join(" ")
49
- .replace(/\s*\/\s*/g, "/")
50
- .trim();
249
+ for (const subbloco of bloco?.blocos ?? []) {
250
+ if (subbloco.tipo !== "bloco_generico") {
251
+ continue;
252
+ }
253
+ const codigo = subbloco.nome ?? subbloco.palavraChave;
254
+ if (!codigo || codigo === "desconhecido") {
255
+ continue;
256
+ }
257
+ erros.set(codigo, {
258
+ codigo,
259
+ mensagem: valorCampoCompleto(localizarCampo(subbloco, "mensagem")) ?? `Erro estruturado "${codigo}".`,
260
+ categoria: valorCampoCompleto(localizarCampo(subbloco, "categoria")),
261
+ recuperabilidade: valorCampoCompleto(localizarCampo(subbloco, "recuperabilidade")),
262
+ acaoChamador: valorCampoCompleto(localizarCampo(subbloco, "acao_chamador")),
263
+ impactaEstado: valorCampoCompleto(localizarCampo(subbloco, "impacta_estado")) === "verdadeiro",
264
+ requerCompensacao: valorCampoCompleto(localizarCampo(subbloco, "requer_compensacao")) === "verdadeiro",
265
+ });
266
+ }
267
+ for (const erro of fallback ?? []) {
268
+ if (!erros.has(erro.codigo)) {
269
+ erros.set(erro.codigo, {
270
+ codigo: erro.codigo,
271
+ mensagem: erro.mensagem,
272
+ categoria: erro.categoria,
273
+ recuperabilidade: erro.recuperabilidade,
274
+ acaoChamador: erro.acaoChamador,
275
+ impactaEstado: erro.impactaEstado,
276
+ requerCompensacao: erro.requerCompensacao,
277
+ });
278
+ }
279
+ }
280
+ return [...erros.values()];
281
+ }
282
+ function extrairPerfil(bloco, padrao = "interno") {
283
+ const perfil = valorCampoCompleto(localizarCampo(bloco, "perfil", "compatibilidade"))?.toLowerCase();
284
+ if (perfil === "publico"
285
+ || perfil === "interno"
286
+ || perfil === "experimental"
287
+ || perfil === "legado"
288
+ || perfil === "deprecado") {
289
+ return perfil;
290
+ }
291
+ return padrao;
292
+ }
293
+ function tipoNaoPrimitivo(campo) {
294
+ if (!TIPOS_PRIMITIVOS.has(campo.tipoBase)) {
295
+ return campo.tipoBase;
296
+ }
297
+ if (campo.tipoItem && !TIPOS_PRIMITIVOS.has(campo.tipoItem)) {
298
+ return campo.tipoItem;
299
+ }
300
+ if (campo.valorMapa && !TIPOS_PRIMITIVOS.has(campo.valorMapa)) {
301
+ return campo.valorMapa;
302
+ }
303
+ return undefined;
304
+ }
305
+ function deduplicarTexto(valores) {
306
+ return [...new Set(valores.filter(Boolean))].sort((a, b) => a.localeCompare(b, "pt-BR"));
307
+ }
308
+ function resumirAgente(params) {
309
+ const entidadesAfetadas = deduplicarTexto([
310
+ ...(params.input ?? []).map(tipoNaoPrimitivo).filter((item) => Boolean(item)),
311
+ ...(params.output ?? []).map(tipoNaoPrimitivo).filter((item) => Boolean(item)),
312
+ ...(params.efeitos ?? []).map((efeito) => efeito.alvo),
313
+ ]);
314
+ const mutacoesPrevistas = deduplicarTexto((params.efeitos ?? []).map((efeito) => `${efeito.categoria}:${efeito.alvo}`));
315
+ const riscos = new Set();
316
+ if ((params.efeitos ?? []).some((efeito) => efeito.categoria === "persistencia")) {
317
+ riscos.add("altera_persistencia");
318
+ }
319
+ if ((params.efeitos ?? []).some((efeito) => efeito.criticidade === "alta" || efeito.criticidade === "critica")) {
320
+ riscos.add("efeito_critico");
321
+ }
322
+ if (params.execucao?.criticidadeOperacional === "alta" || params.execucao?.criticidadeOperacional === "critica") {
323
+ riscos.add("execucao_critica");
324
+ }
325
+ if ((params.vinculos ?? []).length === 0) {
326
+ riscos.add("vinculo_fraco");
327
+ }
328
+ const checks = new Set();
329
+ checks.add("rodar sema validar --json");
330
+ if ((params.output ?? []).length > 0) {
331
+ checks.add("verificar guarantees");
332
+ }
333
+ if ((params.vinculos ?? []).length > 0) {
334
+ checks.add("rodar sema drift --json");
335
+ }
336
+ if (params.superficiePublica) {
337
+ checks.add("validar superficie publica impactada");
338
+ }
339
+ return {
340
+ riscos: [...riscos],
341
+ checks: [...checks],
342
+ entidadesAfetadas,
343
+ superficiesPublicas: params.superficiePublica ? [params.superficiePublica] : [],
344
+ mutacoesPrevistas,
345
+ };
346
+ }
347
+ function recomporCaminho(campo) {
348
+ const valor = valorCampoCompleto(campo);
349
+ return valor?.replace(/\s*\/\s*/g, "/").trim();
51
350
  }
52
351
  function ehUseInterop(use) {
53
352
  return use.origem !== "sema";
54
353
  }
354
+ function converterErroPublico(erro, origemTask) {
355
+ return {
356
+ nome: erro.codigo,
357
+ codigo: erro.codigo,
358
+ mensagem: erro.mensagem,
359
+ categoria: erro.categoria,
360
+ recuperabilidade: erro.recuperabilidade,
361
+ acaoChamador: erro.acaoChamador,
362
+ impactaEstado: erro.impactaEstado,
363
+ requerCompensacao: erro.requerCompensacao,
364
+ origemTask,
365
+ };
366
+ }
367
+ function calcularConfiancaPublica(route) {
368
+ if (route.task && route.vinculos.length > 0) {
369
+ return "alta";
370
+ }
371
+ if (route.task || route.vinculos.length > 0) {
372
+ return "media";
373
+ }
374
+ return "baixa";
375
+ }
376
+ function calcularRiscoPublico(route) {
377
+ if (route.efeitosPublicos.some((efeito) => efeito.categoria === "persistencia" || efeito.criticidade === "critica")) {
378
+ return "alto";
379
+ }
380
+ if (route.efeitosPublicos.length > 0 || route.errosPublicos.length > 0) {
381
+ return "medio";
382
+ }
383
+ return "baixo";
384
+ }
385
+ function converterSuperficie(tipo, superficie) {
386
+ const input = converterCampos(encontrarSubBloco(superficie, "input"));
387
+ const output = converterCampos(encontrarSubBloco(superficie, "output"));
388
+ const effects = (encontrarSubBloco(superficie, "effects")?.linhas ?? [])
389
+ .map((linha) => parsearEfeitoSemantico(linha.conteudo))
390
+ .filter((linha) => Boolean(linha));
391
+ const vinculos = converterVinculos(encontrarSubBloco(superficie, "vinculos"));
392
+ const execucao = converterExecucao(encontrarSubBloco(superficie, "execucao"));
393
+ const task = valorCampoCompleto(localizarCampo(superficie, "task", "tarefa"));
394
+ const perfilCompatibilidade = extrairPerfil(superficie, tipo === "webhook" ? "publico" : "interno");
395
+ const resumoAgente = resumirAgente({
396
+ input,
397
+ output,
398
+ efeitos: effects,
399
+ vinculos,
400
+ execucao,
401
+ superficiePublica: perfilCompatibilidade === "publico" ? `${tipo}:${superficie.nome ?? tipo}` : undefined,
402
+ });
403
+ return {
404
+ tipo,
405
+ nome: superficie.nome ?? tipo,
406
+ campos: converterCampos(superficie),
407
+ linhas: superficie.linhas.map((linha) => linha.conteudo),
408
+ task: task || undefined,
409
+ input,
410
+ output,
411
+ effects,
412
+ implementacoesExternas: converterImplementacoes(encontrarSubBloco(superficie, "impl")),
413
+ vinculos,
414
+ execucao,
415
+ perfilCompatibilidade,
416
+ resumoAgente,
417
+ };
418
+ }
55
419
  export function converterParaIr(modulo, diagnosticos, contexto) {
420
+ const perfilModulo = extrairPerfil(modulo.vinculos, modulo.routes.length > 0 || modulo.webhooks.length > 0 ? "publico" : "interno");
56
421
  const types = modulo.types.map((type) => ({
57
422
  nome: type.nome,
58
423
  definicao: converterBloco(encontrarSubBloco(type.corpo, "fields") ?? type.corpo),
@@ -67,85 +432,88 @@ export function converterParaIr(modulo, diagnosticos, contexto) {
67
432
  .map((linha) => parsearExpressaoSemantica(linha.conteudo))
68
433
  .filter((linha) => Boolean(linha)),
69
434
  }));
70
- const tasks = modulo.tasks.map((task) => ({
71
- nome: task.nome,
72
- input: converterCampos(task.input),
73
- output: converterCampos(task.output),
74
- rules: task.rules?.linhas.map((linha) => linha.conteudo) ?? [],
75
- regrasEstruturadas: (task.rules?.linhas ?? []).map((linha) => parsearExpressaoSemantica(linha.conteudo)).filter((linha) => Boolean(linha)),
76
- effects: task.effects?.linhas.map((linha) => linha.conteudo) ?? [],
77
- efeitosEstruturados: (task.effects?.linhas ?? []).map((linha) => parsearEfeitoSemantico(linha.conteudo)).filter((linha) => Boolean(linha)),
78
- implementacoesExternas: (task.impl?.campos ?? [])
79
- .map((campo) => {
80
- const origem = campo.nome.toLowerCase();
81
- if (origem === "ts" || origem === "typescript") {
82
- return { origem: "ts", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" };
83
- }
84
- if (origem === "py" || origem === "python") {
85
- return { origem: "py", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" };
86
- }
87
- if (origem === "dart") {
88
- return { origem: "dart", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" };
89
- }
90
- if (origem === "cs" || origem === "csharp" || origem === "dotnet") {
91
- return { origem: "cs", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" };
92
- }
93
- if (origem === "java") {
94
- return { origem: "java", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" };
95
- }
96
- if (origem === "go" || origem === "golang") {
97
- return { origem: "go", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" };
98
- }
99
- if (origem === "rust" || origem === "rs") {
100
- return { origem: "rust", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" };
101
- }
102
- if (origem === "cpp" || origem === "cxx" || origem === "cc" || origem === "c++") {
103
- return { origem: "cpp", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" };
104
- }
105
- return undefined;
106
- })
107
- .filter((item) => Boolean(item)),
108
- guarantees: task.guarantees?.linhas.map((linha) => linha.conteudo) ?? [],
109
- garantiasEstruturadas: (task.guarantees?.linhas ?? []).map((linha) => parsearExpressaoSemantica(linha.conteudo)).filter((linha) => Boolean(linha)),
110
- errors: Object.fromEntries((task.error?.campos ?? []).map((campo) => [campo.nome, [campo.valor, ...campo.modificadores].join(" ").trim()])),
111
- stateContract: task.state ? {
112
- nomeEstado: task.state.nome ?? task.state.campos.find((campo) => campo.nome === "state" || campo.nome === "estado")?.valor,
113
- campos: converterCampos(task.state),
114
- linhas: task.state.linhas.map((linha) => linha.conteudo),
115
- transicoes: (encontrarSubBloco(task.state, "transitions")?.linhas ?? task.state.linhas)
116
- .map((linha) => parsearTransicaoEstado(linha.conteudo))
435
+ const tarefasSemanticas = contexto?.tarefasDetalhadas ?? new Map();
436
+ const tasks = modulo.tasks.map((task) => {
437
+ const input = converterCampos(task.input);
438
+ const output = converterCampos(task.output);
439
+ const effects = (task.effects?.linhas ?? [])
440
+ .map((linha) => parsearEfeitoSemantico(linha.conteudo))
441
+ .filter((linha) => Boolean(linha));
442
+ const vinculos = converterVinculos(task.vinculos);
443
+ const execucao = converterExecucao(task.execucao);
444
+ const errosDetalhados = converterErrosTask(task.error, tarefasSemanticas.get(task.nome)?.errors);
445
+ const perfilCompatibilidade = extrairPerfil(task.corpo, "interno");
446
+ const resumoAgente = resumirAgente({
447
+ input,
448
+ output,
449
+ efeitos: effects,
450
+ vinculos,
451
+ execucao,
452
+ });
453
+ return {
454
+ nome: task.nome,
455
+ input,
456
+ output,
457
+ rules: task.rules?.linhas.map((linha) => linha.conteudo) ?? [],
458
+ regrasEstruturadas: (task.rules?.linhas ?? [])
459
+ .map((linha) => parsearExpressaoSemantica(linha.conteudo))
117
460
  .filter((linha) => Boolean(linha)),
118
- } : undefined,
119
- tests: (task.tests?.blocos.filter((bloco) => bloco.tipo === "caso_teste") ?? []).map(converterCaso),
120
- }));
461
+ effects: task.effects?.linhas.map((linha) => linha.conteudo) ?? [],
462
+ efeitosEstruturados: effects,
463
+ implementacoesExternas: converterImplementacoes(task.impl),
464
+ vinculos,
465
+ execucao,
466
+ guarantees: task.guarantees?.linhas.map((linha) => linha.conteudo) ?? [],
467
+ garantiasEstruturadas: (task.guarantees?.linhas ?? [])
468
+ .map((linha) => parsearExpressaoSemantica(linha.conteudo))
469
+ .filter((linha) => Boolean(linha)),
470
+ errors: Object.fromEntries(errosDetalhados.map((erro) => [erro.codigo, erro.mensagem])),
471
+ errosDetalhados,
472
+ perfilCompatibilidade,
473
+ stateContract: task.state ? {
474
+ nomeEstado: task.state.nome ?? task.state.campos.find((campo) => campo.nome === "state" || campo.nome === "estado")?.valor,
475
+ campos: converterCampos(task.state),
476
+ linhas: task.state.linhas.map((linha) => linha.conteudo),
477
+ transicoes: (encontrarSubBloco(task.state, "transitions")?.linhas ?? task.state.linhas)
478
+ .map((linha) => parsearTransicaoEstado(linha.conteudo))
479
+ .filter((linha) => Boolean(linha)),
480
+ } : undefined,
481
+ resumoAgente,
482
+ tests: (task.tests?.blocos.filter((bloco) => bloco.tipo === "caso_teste") ?? []).map(converterCaso),
483
+ };
484
+ });
121
485
  const tarefasPorNome = new Map(tasks.map((task) => [task.nome, task]));
122
- const tarefasSemanticas = contexto?.tarefasDetalhadas ?? new Map();
123
- const flows = modulo.flows.map((flow) => ({
124
- nome: flow.nome,
125
- campos: flow.corpo.campos.map((campo) => ({
126
- nome: campo.nome,
127
- tipo: campo.valor,
128
- modificadores: campo.modificadores,
129
- })),
130
- linhas: flow.corpo.linhas.map((linha) => linha.conteudo),
131
- tasksReferenciadas: flow.corpo.campos
132
- .filter((campo) => campo.nome === "task" || campo.nome === "tarefa")
133
- .map((campo) => campo.valor),
134
- etapasEstruturadas: flow.corpo.linhas
135
- .map((linha) => parsearEtapaFlow(linha.conteudo))
136
- .filter((linha) => Boolean(linha)),
137
- effects: (encontrarSubBloco(flow.corpo, "effects")?.linhas ?? []).map((linha) => linha.conteudo),
138
- efeitosEstruturados: (encontrarSubBloco(flow.corpo, "effects")?.linhas ?? [])
486
+ const flows = modulo.flows.map((flow) => {
487
+ const campos = converterCampos(flow.corpo);
488
+ const effects = (encontrarSubBloco(flow.corpo, "effects")?.linhas ?? [])
139
489
  .map((linha) => parsearEfeitoSemantico(linha.conteudo))
140
- .filter((linha) => Boolean(linha)),
141
- }));
490
+ .filter((linha) => Boolean(linha));
491
+ const vinculos = converterVinculos(flow.vinculos);
492
+ const perfilCompatibilidade = extrairPerfil(flow.corpo, "interno");
493
+ return {
494
+ nome: flow.nome,
495
+ campos,
496
+ linhas: flow.corpo.linhas.map((linha) => linha.conteudo),
497
+ tasksReferenciadas: flow.corpo.campos
498
+ .filter((campo) => campo.nome === "task" || campo.nome === "tarefa")
499
+ .map((campo) => campo.valor),
500
+ etapasEstruturadas: flow.corpo.linhas
501
+ .map((linha) => parsearEtapaFlow(linha.conteudo))
502
+ .filter((linha) => Boolean(linha)),
503
+ effects: (encontrarSubBloco(flow.corpo, "effects")?.linhas ?? []).map((linha) => linha.conteudo),
504
+ efeitosEstruturados: effects,
505
+ vinculos,
506
+ perfilCompatibilidade,
507
+ resumoAgente: resumirAgente({
508
+ input: campos,
509
+ efeitos: effects,
510
+ vinculos,
511
+ }),
512
+ };
513
+ });
142
514
  const routes = modulo.routes.map((route) => ({
143
515
  nome: route.nome,
144
- campos: route.corpo.campos.map((campo) => ({
145
- nome: campo.nome,
146
- tipo: campo.valor,
147
- modificadores: campo.modificadores,
148
- })),
516
+ campos: converterCampos(route.corpo),
149
517
  linhas: route.corpo.linhas.map((linha) => linha.conteudo),
150
518
  metodo: route.corpo.campos.find((campo) => campo.nome === "metodo")?.valor,
151
519
  caminho: recomporCaminho(route.corpo.campos.find((campo) => campo.nome === "caminho")),
@@ -154,7 +522,16 @@ export function converterParaIr(modulo, diagnosticos, contexto) {
154
522
  outputPublico: [],
155
523
  errosPublicos: [],
156
524
  efeitosPublicos: [],
525
+ vinculos: converterVinculos(route.vinculos),
526
+ perfilCompatibilidade: extrairPerfil(route.corpo, "publico"),
157
527
  garantiasPublicasMinimas: [],
528
+ resumoAgente: {
529
+ riscos: [],
530
+ checks: [],
531
+ entidadesAfetadas: [],
532
+ superficiesPublicas: [],
533
+ mutacoesPrevistas: [],
534
+ },
158
535
  publico: {
159
536
  metodo: undefined,
160
537
  caminho: undefined,
@@ -171,32 +548,57 @@ export function converterParaIr(modulo, diagnosticos, contexto) {
171
548
  const tarefaSemantica = route.task ? tarefasSemanticas.get(route.task) : undefined;
172
549
  const inputPublicoDeclarado = converterCampos(encontrarSubBloco(routeAst.corpo, "input"));
173
550
  const outputPublicoDeclarado = converterCampos(encontrarSubBloco(routeAst.corpo, "output"));
174
- const errosPublicosDeclarados = converterErrosPublicos(encontrarSubBloco(routeAst.corpo, "error"));
551
+ const errosDeclarados = converterErrosTask(encontrarSubBloco(routeAst.corpo, "error"), tarefaSemantica?.errors);
175
552
  const efeitosPublicosDeclarados = (encontrarSubBloco(routeAst.corpo, "effects")?.linhas ?? [])
176
553
  .map((linha) => parsearEfeitoSemantico(linha.conteudo))
177
554
  .filter((linha) => Boolean(linha));
178
555
  const inputPublicoResolvido = inputPublicoDeclarado.length > 0
179
556
  ? inputPublicoDeclarado
180
- : (tarefaAssociada?.input ?? tarefaSemantica?.input ?? []);
557
+ : (tarefaAssociada?.input ?? tarefaSemantica?.input?.map((campo) => ({
558
+ nome: campo.nome,
559
+ tipo: campo.tipo,
560
+ modificadores: campo.modificadores,
561
+ tipoOriginal: campo.tipo,
562
+ tipoBase: campo.tipo,
563
+ cardinalidade: "unitario",
564
+ opcional: false,
565
+ tiposAlternativos: [],
566
+ refinamentos: [],
567
+ })) ?? []);
181
568
  const outputPublicoResolvido = outputPublicoDeclarado.length > 0
182
569
  ? outputPublicoDeclarado
183
- : (tarefaAssociada?.output ?? tarefaSemantica?.output ?? []);
184
- const errosPublicosResolvidos = errosPublicosDeclarados.length > 0
185
- ? errosPublicosDeclarados
186
- : (tarefaAssociada
187
- ? Object.entries(tarefaAssociada.errors).map(([nome, mensagem]) => ({ nome, codigo: nome, mensagem, origemTask: route.task }))
188
- : (tarefaSemantica?.errors ?? []).map((erro) => ({ nome: erro.codigo, codigo: erro.codigo, mensagem: erro.mensagem, origemTask: route.task })));
570
+ : (tarefaAssociada?.output ?? tarefaSemantica?.output?.map((campo) => ({
571
+ nome: campo.nome,
572
+ tipo: campo.tipo,
573
+ modificadores: campo.modificadores,
574
+ tipoOriginal: campo.tipo,
575
+ tipoBase: campo.tipo,
576
+ cardinalidade: "unitario",
577
+ opcional: false,
578
+ tiposAlternativos: [],
579
+ refinamentos: [],
580
+ })) ?? []);
581
+ const errosPublicosResolvidos = errosDeclarados.length > 0
582
+ ? errosDeclarados.map((erro) => converterErroPublico(erro, route.task))
583
+ : (tarefaAssociada?.errosDetalhados ?? (tarefaSemantica?.errors ?? []).map((erro) => ({ codigo: erro.codigo, mensagem: erro.mensagem }))).map((erro) => converterErroPublico(erro, route.task));
189
584
  const garantiasPublicasMinimas = (tarefaAssociada?.guarantees ?? tarefaSemantica?.guarantees ?? []).filter((garantia) => {
190
585
  const referencia = garantia.trim().split(/\s+/)[0] ?? "";
191
586
  return outputPublicoResolvido.some((campo) => campo.nome === referencia || garantia.includes(`${campo.nome}.`));
192
587
  });
193
- return {
588
+ const routeResolvida = {
194
589
  ...route,
195
590
  inputPublico: inputPublicoResolvido,
196
591
  outputPublico: outputPublicoResolvido,
197
592
  errosPublicos: errosPublicosResolvidos,
198
593
  efeitosPublicos: efeitosPublicosDeclarados,
199
594
  garantiasPublicasMinimas,
595
+ resumoAgente: resumirAgente({
596
+ input: inputPublicoResolvido,
597
+ output: outputPublicoResolvido,
598
+ efeitos: efeitosPublicosDeclarados,
599
+ vinculos: route.vinculos,
600
+ superficiePublica: `${route.metodo ?? "?"} ${route.caminho ?? "?"}`,
601
+ }),
200
602
  publico: {
201
603
  metodo: route.metodo,
202
604
  caminho: route.caminho,
@@ -206,10 +608,25 @@ export function converterParaIr(modulo, diagnosticos, contexto) {
206
608
  errors: errosPublicosResolvidos,
207
609
  effects: efeitosPublicosDeclarados,
208
610
  garantiasMinimas: garantiasPublicasMinimas,
611
+ confiancaContrato: "media",
612
+ riscoRegressao: "medio",
209
613
  divergenciasPublicas: [],
210
614
  },
211
615
  };
616
+ routeResolvida.publico.confiancaContrato = calcularConfiancaPublica(routeResolvida);
617
+ routeResolvida.publico.riscoRegressao = calcularRiscoPublico(routeResolvida);
618
+ return routeResolvida;
212
619
  });
620
+ const superficies = [
621
+ ...modulo.workers.map((item) => converterSuperficie("worker", item)),
622
+ ...modulo.eventos.map((item) => converterSuperficie("evento", item)),
623
+ ...modulo.filas.map((item) => converterSuperficie("fila", item)),
624
+ ...modulo.crons.map((item) => converterSuperficie("cron", item)),
625
+ ...modulo.webhooks.map((item) => converterSuperficie("webhook", item)),
626
+ ...modulo.caches.map((item) => converterSuperficie("cache", item)),
627
+ ...modulo.storages.map((item) => converterSuperficie("storage", item)),
628
+ ...modulo.policies.map((item) => converterSuperficie("policy", item)),
629
+ ];
213
630
  const states = modulo.states.map((state) => ({
214
631
  nome: state.nome,
215
632
  campos: converterCampos(encontrarSubBloco(state.corpo, "fields") ?? state.corpo),
@@ -221,6 +638,21 @@ export function converterParaIr(modulo, diagnosticos, contexto) {
221
638
  .map((linha) => parsearTransicaoEstado(linha.conteudo))
222
639
  .filter((linha) => Boolean(linha)),
223
640
  }));
641
+ const resumoAgenteModulo = resumirAgente({
642
+ input: [],
643
+ output: [],
644
+ efeitos: [
645
+ ...tasks.flatMap((task) => task.efeitosEstruturados),
646
+ ...routes.flatMap((route) => route.efeitosPublicos),
647
+ ...superficies.flatMap((superficie) => superficie.effects),
648
+ ],
649
+ vinculos: [
650
+ ...converterVinculos(modulo.vinculos),
651
+ ...tasks.flatMap((task) => task.vinculos),
652
+ ...routes.flatMap((route) => route.vinculos),
653
+ ...superficies.flatMap((superficie) => superficie.vinculos),
654
+ ],
655
+ });
224
656
  return {
225
657
  nome: modulo.nome,
226
658
  uses: contexto?.modulosImportados.length
@@ -234,13 +666,25 @@ export function converterParaIr(modulo, diagnosticos, contexto) {
234
666
  interoperabilidades: contexto?.interoperabilidades.map((interop) => ({ ...interop })) ?? modulo.uses
235
667
  .filter(ehUseInterop)
236
668
  .map((use) => ({ origem: use.origem, caminho: use.caminho })),
669
+ vinculos: converterVinculos(modulo.vinculos),
670
+ perfilCompatibilidade: perfilModulo,
237
671
  types,
238
672
  entities,
239
673
  enums: modulo.enums.map((enumeracao) => ({ nome: enumeracao.nome, valores: enumeracao.valores })),
240
674
  tasks,
241
675
  flows,
242
676
  routes,
677
+ superficies,
243
678
  states,
679
+ resumoAgente: {
680
+ ...resumoAgenteModulo,
681
+ superficiesPublicas: deduplicarTexto([
682
+ ...routes.map((route) => `${route.metodo ?? "?"} ${route.caminho ?? route.nome}`),
683
+ ...superficies
684
+ .filter((superficie) => superficie.perfilCompatibilidade === "publico")
685
+ .map((superficie) => `${superficie.tipo}:${superficie.nome}`),
686
+ ]),
687
+ },
244
688
  diagnosticos,
245
689
  };
246
690
  }