@semacode/cli 1.5.29 → 1.5.30

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 (85) hide show
  1. package/dist/comandos.js +36 -0
  2. package/dist/comandos.js.map +1 -1
  3. package/dist/guard.d.ts +35 -0
  4. package/dist/guard.js +164 -0
  5. package/dist/guard.js.map +1 -0
  6. package/exemplos/.prepack-generated +1 -0
  7. package/node_modules/@sema/gerador-css/package.json +14 -7
  8. package/node_modules/@sema/gerador-css/src/index.ts +605 -0
  9. package/node_modules/@sema/gerador-css/tsconfig.json +13 -0
  10. package/node_modules/@sema/gerador-css/tsconfig.tsbuildinfo +1 -0
  11. package/node_modules/@sema/gerador-dart/package.json +14 -7
  12. package/node_modules/@sema/gerador-dart/src/index.ts +52 -0
  13. package/node_modules/@sema/gerador-dart/tsconfig.json +13 -0
  14. package/node_modules/@sema/gerador-dart/tsconfig.tsbuildinfo +1 -0
  15. package/node_modules/@sema/gerador-html/package.json +14 -7
  16. package/node_modules/@sema/gerador-html/src/index.ts +185 -0
  17. package/node_modules/@sema/gerador-html/tsconfig.json +13 -0
  18. package/node_modules/@sema/gerador-html/tsconfig.tsbuildinfo +1 -0
  19. package/node_modules/@sema/gerador-javascript/package.json +14 -7
  20. package/node_modules/@sema/gerador-javascript/src/index.ts +461 -0
  21. package/node_modules/@sema/gerador-javascript/tsconfig.json +13 -0
  22. package/node_modules/@sema/gerador-javascript/tsconfig.tsbuildinfo +1 -0
  23. package/node_modules/@sema/gerador-lua/package.json +14 -7
  24. package/node_modules/@sema/gerador-lua/src/index.ts +359 -0
  25. package/node_modules/@sema/gerador-lua/tsconfig.json +13 -0
  26. package/node_modules/@sema/gerador-lua/tsconfig.tsbuildinfo +1 -0
  27. package/node_modules/@sema/gerador-python/package.json +14 -7
  28. package/node_modules/@sema/gerador-python/src/index.ts +850 -0
  29. package/node_modules/@sema/gerador-python/tsconfig.json +13 -0
  30. package/node_modules/@sema/gerador-python/tsconfig.tsbuildinfo +1 -0
  31. package/node_modules/@sema/gerador-typescript/package.json +14 -7
  32. package/node_modules/@sema/gerador-typescript/src/index.ts +876 -0
  33. package/node_modules/@sema/gerador-typescript/tsconfig.json +13 -0
  34. package/node_modules/@sema/gerador-typescript/tsconfig.tsbuildinfo +1 -0
  35. package/node_modules/@sema/nucleo/package.json +10 -7
  36. package/node_modules/@sema/nucleo/src/ast/tipos.ts +207 -0
  37. package/node_modules/@sema/nucleo/src/diagnosticos/index.ts +43 -0
  38. package/node_modules/@sema/nucleo/src/formatador/index.ts +530 -0
  39. package/node_modules/@sema/nucleo/src/index.ts +183 -0
  40. package/node_modules/@sema/nucleo/src/ir/conversor.ts +1037 -0
  41. package/node_modules/@sema/nucleo/src/ir/modelos.ts +403 -0
  42. package/node_modules/@sema/nucleo/src/lexer/lexer.ts +166 -0
  43. package/node_modules/@sema/nucleo/src/lexer/tokens.ts +79 -0
  44. package/node_modules/@sema/nucleo/src/parser/gramatica.ebnf +41 -0
  45. package/node_modules/@sema/nucleo/src/parser/parser.ts +936 -0
  46. package/node_modules/@sema/nucleo/src/persistencia/contratos.ts +379 -0
  47. package/node_modules/@sema/nucleo/src/semantico/analisador.ts +3126 -0
  48. package/node_modules/@sema/nucleo/src/semantico/estruturas.ts +665 -0
  49. package/node_modules/@sema/nucleo/src/semantico/seguranca.ts +362 -0
  50. package/node_modules/@sema/nucleo/src/util/arquivos.ts +28 -0
  51. package/node_modules/@sema/nucleo/tsconfig.json +9 -0
  52. package/node_modules/@sema/nucleo/tsconfig.tsbuildinfo +1 -0
  53. package/node_modules/@sema/padroes/package.json +10 -7
  54. package/node_modules/@sema/padroes/src/index.ts +382 -0
  55. package/node_modules/@sema/padroes/tsconfig.json +9 -0
  56. package/node_modules/@sema/padroes/tsconfig.tsbuildinfo +1 -0
  57. package/package.json +74 -75
  58. package/AGENTS.md +0 -294
  59. package/AGENT_CONTEXT_PACK.json +0 -164
  60. package/LICENSE +0 -22
  61. package/SEMA_BRIEF.curto.txt +0 -11
  62. package/SEMA_BRIEF.md +0 -511
  63. package/SEMA_BRIEF.micro.txt +0 -9
  64. package/SEMA_INDEX.json +0 -7588
  65. package/docs/AGENT_STARTER.md +0 -109
  66. package/docs/api.md +0 -82
  67. package/docs/cli.md +0 -175
  68. package/docs/como-ensinar-a-sema-para-ia.md +0 -155
  69. package/docs/deploy.md +0 -93
  70. package/docs/documentacao.md +0 -88
  71. package/docs/env.md +0 -105
  72. package/docs/extensao-vscode.md +0 -53
  73. package/docs/fluxo-pratico-ia-sema.md +0 -187
  74. package/docs/instalacao-e-primeiro-uso.md +0 -134
  75. package/docs/integracao-com-ia.md +0 -110
  76. package/docs/mcp.md +0 -292
  77. package/docs/pagamento-ponta-a-ponta.md +0 -171
  78. package/docs/persistencia-vendor-first.md +0 -151
  79. package/docs/prompt-base-ia-sema.md +0 -111
  80. package/docs/repositories.md +0 -54
  81. package/docs/rollback.md +0 -49
  82. package/docs/seguranca.md +0 -126
  83. package/docs/sintaxe.md +0 -218
  84. package/llms-full.txt +0 -35
  85. package/llms.txt +0 -18
@@ -0,0 +1,1037 @@
1
+ import type { BlocoCasoTesteAst, BlocoGenericoAst, CampoAst, ModuloAst } from "../ast/tipos.js";
2
+ import type { Diagnostico } from "../diagnosticos/index.js";
3
+ import {
4
+ localizarCampoPersistencia,
5
+ matrizCompatibilidadePersistencia,
6
+ nomeTipoRecursoPersistencia,
7
+ normalizarConsistenciaPersistencia,
8
+ normalizarDurabilidadePersistencia,
9
+ normalizarEngineBanco,
10
+ normalizarModeloConsultaPersistencia,
11
+ normalizarModeloTransacaoPersistencia,
12
+ parsearBooleanoPersistencia,
13
+ TIPOS_RECURSO_PERSISTENCIA,
14
+ type TipoRecursoPersistencia,
15
+ } from "../persistencia/contratos.js";
16
+ import type { ContextoSemantico, ErroSemanticoTask } from "../semantico/analisador.js";
17
+ import {
18
+ contratoDadosTemSensivel,
19
+ extrairContratoAudit,
20
+ extrairContratoAuth,
21
+ extrairContratoAuthz,
22
+ extrairContratoDados,
23
+ extrairContratoForbidden,
24
+ extrairContratoSegredos,
25
+ efeitoEhPrivilegiado,
26
+ } from "../semantico/seguranca.js";
27
+ import { parsearEfeitoSemantico, parsearEtapaFlow, parsearExpressaoSemantica, parsearTransicaoEstado } from "../semantico/estruturas.js";
28
+ import type {
29
+ IrBlocoDeclarativo,
30
+ IrCampo,
31
+ IrCasoTeste,
32
+ IrAudit,
33
+ IrAuth,
34
+ IrAuthz,
35
+ IrDados,
36
+ IrEntity,
37
+ IrErroOperacional,
38
+ IrExecucao,
39
+ IrForbidden,
40
+ IrFlow,
41
+ IrImplementacaoTask,
42
+ IrBancoDados,
43
+ IrCompatibilidadePersistencia,
44
+ IrModulo,
45
+ IrRecursoPersistencia,
46
+ IrResumoAgente,
47
+ IrRoute,
48
+ IrRoutePublica,
49
+ IrSegredos,
50
+ IrState,
51
+ IrSuperficie,
52
+ IrTask,
53
+ IrType,
54
+ IrVinculo,
55
+ NivelConfiancaSemantica,
56
+ NivelRiscoSemantico,
57
+ PerfilCompatibilidade,
58
+ TipoSuperficieIr,
59
+ } from "./modelos.js";
60
+
61
+ const TIPOS_PRIMITIVOS = new Set([
62
+ "Texto",
63
+ "Numero",
64
+ "Inteiro",
65
+ "Decimal",
66
+ "Booleano",
67
+ "Data",
68
+ "DataHora",
69
+ "Timestamp",
70
+ "Id",
71
+ "Email",
72
+ "Url",
73
+ "Json",
74
+ "Objeto",
75
+ "Vazio",
76
+ ]);
77
+
78
+ function encontrarSubBloco(bloco: BlocoGenericoAst, palavraChave: string): BlocoGenericoAst | undefined {
79
+ return bloco.blocos.find((subbloco): subbloco is BlocoGenericoAst => subbloco.tipo === "bloco_generico" && subbloco.palavraChave === palavraChave);
80
+ }
81
+
82
+ function localizarCampo(bloco: BlocoGenericoAst | undefined, ...nomes: string[]): CampoAst | undefined {
83
+ return bloco?.campos.find((campo) => nomes.includes(campo.nome));
84
+ }
85
+
86
+ function valorCampoCompleto(campo?: CampoAst): string | undefined {
87
+ if (!campo) {
88
+ return undefined;
89
+ }
90
+ return [campo.valor, ...campo.modificadores].join(" ").trim() || undefined;
91
+ }
92
+
93
+ function normalizarTipoDeclarado(tipo: string): string {
94
+ return tipo
95
+ .replace(/\s*([<>\[\](),|?])\s*/g, "$1")
96
+ .replace(/\s+/g, "")
97
+ .trim();
98
+ }
99
+
100
+ function dividirNoNivelRaiz(texto: string, separador: string): string[] {
101
+ const partes: string[] = [];
102
+ let profundidadeAngular = 0;
103
+ let profundidadeColchete = 0;
104
+ let inicio = 0;
105
+
106
+ for (let indice = 0; indice < texto.length; indice += 1) {
107
+ const caractere = texto[indice]!;
108
+ if (caractere === "<") {
109
+ profundidadeAngular += 1;
110
+ continue;
111
+ }
112
+ if (caractere === ">") {
113
+ profundidadeAngular = Math.max(0, profundidadeAngular - 1);
114
+ continue;
115
+ }
116
+ if (caractere === "[") {
117
+ profundidadeColchete += 1;
118
+ continue;
119
+ }
120
+ if (caractere === "]") {
121
+ profundidadeColchete = Math.max(0, profundidadeColchete - 1);
122
+ continue;
123
+ }
124
+ if (profundidadeAngular === 0 && profundidadeColchete === 0 && texto.startsWith(separador, indice)) {
125
+ partes.push(texto.slice(inicio, indice));
126
+ inicio = indice + separador.length;
127
+ indice += separador.length - 1;
128
+ }
129
+ }
130
+
131
+ partes.push(texto.slice(inicio));
132
+ return partes.map((parte) => parte.trim()).filter(Boolean);
133
+ }
134
+
135
+ function analisarCampoTipo(tipo: string, modificadores: string[]): Omit<IrCampo, "nome"> {
136
+ const tipoOriginal = normalizarTipoDeclarado(tipo);
137
+ const modificadoresNormalizados = modificadores.map((item) => item.trim()).filter(Boolean);
138
+ const refinamentos = modificadoresNormalizados.filter((item) => !["required", "optional", "opcional"].includes(item));
139
+ const opcionalPorModificador = modificadoresNormalizados.includes("optional") || modificadoresNormalizados.includes("opcional");
140
+
141
+ let tipoBase = tipoOriginal;
142
+ let cardinalidade: IrCampo["cardinalidade"] = "unitario";
143
+ let tiposAlternativos: string[] = [];
144
+ let tipoItem: string | undefined;
145
+ let chaveMapa: string | undefined;
146
+ let valorMapa: string | undefined;
147
+ let opcional = opcionalPorModificador;
148
+
149
+ if (tipoBase.endsWith("?")) {
150
+ opcional = true;
151
+ tipoBase = tipoBase.slice(0, -1);
152
+ }
153
+
154
+ if (/^Opcional<.+>$/.test(tipoBase)) {
155
+ opcional = true;
156
+ tipoBase = tipoBase.slice("Opcional<".length, -1);
157
+ }
158
+
159
+ const uniao = dividirNoNivelRaiz(tipoBase, "|");
160
+ if (uniao.length > 1) {
161
+ cardinalidade = "uniao";
162
+ tiposAlternativos = uniao.map(normalizarTipoDeclarado);
163
+ tipoBase = tiposAlternativos[0] ?? tipoBase;
164
+ } else if (/^Lista<.+>$/.test(tipoBase)) {
165
+ cardinalidade = "lista";
166
+ tipoItem = tipoBase.slice("Lista<".length, -1).trim();
167
+ tipoBase = tipoItem;
168
+ } else if (/^Mapa<.+>$/.test(tipoBase)) {
169
+ cardinalidade = "mapa";
170
+ const partesMapa = dividirNoNivelRaiz(tipoBase.slice("Mapa<".length, -1), ",");
171
+ chaveMapa = partesMapa[0];
172
+ valorMapa = partesMapa[1];
173
+ tipoBase = valorMapa ?? tipoBase;
174
+ }
175
+
176
+ return {
177
+ tipo: tipoOriginal,
178
+ modificadores: modificadoresNormalizados,
179
+ tipoOriginal,
180
+ tipoBase,
181
+ cardinalidade,
182
+ opcional,
183
+ tiposAlternativos,
184
+ tipoItem,
185
+ chaveMapa,
186
+ valorMapa,
187
+ refinamentos,
188
+ };
189
+ }
190
+
191
+ function converterCampo(campo: CampoAst): IrCampo {
192
+ return {
193
+ nome: campo.nome,
194
+ ...analisarCampoTipo(campo.valor, campo.modificadores),
195
+ };
196
+ }
197
+
198
+ function converterCampos(bloco?: BlocoGenericoAst): IrCampo[] {
199
+ if (!bloco) {
200
+ return [];
201
+ }
202
+ return bloco.campos.map(converterCampo);
203
+ }
204
+
205
+ function converterBloco(bloco?: BlocoGenericoAst): IrBlocoDeclarativo {
206
+ return {
207
+ campos: converterCampos(bloco),
208
+ linhas: bloco?.linhas.map((linha) => linha.conteudo) ?? [],
209
+ blocos: (bloco?.blocos ?? [])
210
+ .filter((subbloco): subbloco is BlocoGenericoAst => subbloco.tipo === "bloco_generico")
211
+ .map((subbloco) => ({
212
+ nome: subbloco.nome ?? subbloco.palavraChave,
213
+ conteudo: converterBloco(subbloco),
214
+ })),
215
+ };
216
+ }
217
+
218
+ function converterCaso(caso: BlocoCasoTesteAst): IrCasoTeste {
219
+ return {
220
+ nome: caso.nome,
221
+ given: converterBloco(caso.given),
222
+ when: caso.when ? converterBloco(caso.when) : undefined,
223
+ expect: converterBloco(caso.expect),
224
+ error: caso.error ? converterBloco(caso.error) : undefined,
225
+ };
226
+ }
227
+
228
+ function coletarLinhasPersistencia(bloco: BlocoGenericoAst | undefined, nome: string): string[] {
229
+ if (!bloco) {
230
+ return [];
231
+ }
232
+ return encontrarSubBloco(bloco, nome)?.linhas.map((linha) => linha.conteudo) ?? [];
233
+ }
234
+
235
+ function resolverTipoRecursoPersistencia(bloco: BlocoGenericoAst): TipoRecursoPersistencia | undefined {
236
+ const explicito = valorCampoCompleto(localizarCampoPersistencia(bloco, "resource_kind"));
237
+ if (explicito && TIPOS_RECURSO_PERSISTENCIA.has(explicito as TipoRecursoPersistencia)) {
238
+ return explicito as TipoRecursoPersistencia;
239
+ }
240
+ return nomeTipoRecursoPersistencia(bloco);
241
+ }
242
+
243
+ function converterCompatibilidadePersistencia(
244
+ compatibilidades: ReturnType<typeof matrizCompatibilidadePersistencia>,
245
+ ): IrCompatibilidadePersistencia[] {
246
+ return compatibilidades.map((item) => ({ ...item }));
247
+ }
248
+
249
+ function converterRecursoPersistencia(recurso: BlocoGenericoAst): IrRecursoPersistencia | undefined {
250
+ const resourceKind = resolverTipoRecursoPersistencia(recurso);
251
+ if (!resourceKind) {
252
+ return undefined;
253
+ }
254
+
255
+ const mode = valorCampoCompleto(localizarCampoPersistencia(recurso, "mode"));
256
+ const isolation = valorCampoCompleto(localizarCampoPersistencia(recurso, "isolation"));
257
+
258
+ return {
259
+ nome: recurso.nome ?? resourceKind,
260
+ resourceKind,
261
+ entity: valorCampoCompleto(localizarCampoPersistencia(recurso, "entity")),
262
+ collection: valorCampoCompleto(localizarCampoPersistencia(recurso, "collection")),
263
+ table: valorCampoCompleto(localizarCampoPersistencia(recurso, "table")),
264
+ consistency: normalizarConsistenciaPersistencia(valorCampoCompleto(localizarCampoPersistencia(recurso, "consistency")))
265
+ ?? valorCampoCompleto(localizarCampoPersistencia(recurso, "consistency")),
266
+ durability: normalizarDurabilidadePersistencia(valorCampoCompleto(localizarCampoPersistencia(recurso, "durability")))
267
+ ?? valorCampoCompleto(localizarCampoPersistencia(recurso, "durability")),
268
+ transactionModel: normalizarModeloTransacaoPersistencia(valorCampoCompleto(localizarCampoPersistencia(recurso, "transaction_model")))
269
+ ?? valorCampoCompleto(localizarCampoPersistencia(recurso, "transaction_model")),
270
+ queryModel: normalizarModeloConsultaPersistencia(valorCampoCompleto(localizarCampoPersistencia(recurso, "query_model")))
271
+ ?? valorCampoCompleto(localizarCampoPersistencia(recurso, "query_model")),
272
+ mode,
273
+ isolation,
274
+ strategy: valorCampoCompleto(localizarCampoPersistencia(recurso, "strategy")),
275
+ ttl: valorCampoCompleto(localizarCampoPersistencia(recurso, "ttl")),
276
+ retention: valorCampoCompleto(localizarCampoPersistencia(recurso, "retention")),
277
+ path: valorCampoCompleto(localizarCampoPersistencia(recurso, "path")),
278
+ from: valorCampoCompleto(localizarCampoPersistencia(recurso, "from")),
279
+ to: valorCampoCompleto(localizarCampoPersistencia(recurso, "to")),
280
+ surface: valorCampoCompleto(localizarCampoPersistencia(recurso, "surface")),
281
+ adapter: valorCampoCompleto(localizarCampoPersistencia(recurso, "adapter")),
282
+ portavel: parsearBooleanoPersistencia(valorCampoCompleto(localizarCampoPersistencia(recurso, "portavel"))),
283
+ capabilities: coletarLinhasPersistencia(recurso, "capabilities"),
284
+ operations: coletarLinhasPersistencia(recurso, "operations"),
285
+ indexing: coletarLinhasPersistencia(recurso, "indexing"),
286
+ guarantees: coletarLinhasPersistencia(recurso, "guarantees"),
287
+ diagnostics: coletarLinhasPersistencia(recurso, "diagnostics"),
288
+ risks: coletarLinhasPersistencia(recurso, "risks"),
289
+ fields: converterCampos(recurso),
290
+ lines: recurso.linhas.map((linha) => linha.conteudo),
291
+ block: converterBloco(recurso),
292
+ compatibilidade: converterCompatibilidadePersistencia(matrizCompatibilidadePersistencia(resourceKind, { mode, isolation })),
293
+ };
294
+ }
295
+
296
+ function converterDatabase(database: BlocoGenericoAst): IrBancoDados {
297
+ return {
298
+ nome: database.nome ?? "database",
299
+ engine: normalizarEngineBanco(valorCampoCompleto(localizarCampoPersistencia(database, "engine"))),
300
+ schema: valorCampoCompleto(localizarCampoPersistencia(database, "schema")),
301
+ database: valorCampoCompleto(localizarCampoPersistencia(database, "database")),
302
+ consistency: normalizarConsistenciaPersistencia(valorCampoCompleto(localizarCampoPersistencia(database, "consistency")))
303
+ ?? valorCampoCompleto(localizarCampoPersistencia(database, "consistency")),
304
+ durability: normalizarDurabilidadePersistencia(valorCampoCompleto(localizarCampoPersistencia(database, "durability")))
305
+ ?? valorCampoCompleto(localizarCampoPersistencia(database, "durability")),
306
+ transactionModel: normalizarModeloTransacaoPersistencia(valorCampoCompleto(localizarCampoPersistencia(database, "transaction_model")))
307
+ ?? valorCampoCompleto(localizarCampoPersistencia(database, "transaction_model")),
308
+ queryModel: normalizarModeloConsultaPersistencia(valorCampoCompleto(localizarCampoPersistencia(database, "query_model")))
309
+ ?? valorCampoCompleto(localizarCampoPersistencia(database, "query_model")),
310
+ portavel: parsearBooleanoPersistencia(valorCampoCompleto(localizarCampoPersistencia(database, "portavel"))),
311
+ adapter: valorCampoCompleto(localizarCampoPersistencia(database, "adapter")),
312
+ capabilities: coletarLinhasPersistencia(database, "capabilities"),
313
+ operations: coletarLinhasPersistencia(database, "operations"),
314
+ indexing: coletarLinhasPersistencia(database, "indexing"),
315
+ guarantees: coletarLinhasPersistencia(database, "guarantees"),
316
+ diagnostics: coletarLinhasPersistencia(database, "diagnostics"),
317
+ risks: coletarLinhasPersistencia(database, "risks"),
318
+ fields: converterCampos(database),
319
+ lines: database.linhas.map((linha) => linha.conteudo),
320
+ block: converterBloco(database),
321
+ resources: database.blocos
322
+ .filter((bloco): bloco is BlocoGenericoAst => bloco.tipo === "bloco_generico")
323
+ .map(converterRecursoPersistencia)
324
+ .filter((item): item is IrRecursoPersistencia => Boolean(item)),
325
+ };
326
+ }
327
+
328
+ function converterImplementacoes(bloco?: BlocoGenericoAst): IrImplementacaoTask[] {
329
+ const implementacoes: IrImplementacaoTask[] = [];
330
+ for (const campo of bloco?.campos ?? []) {
331
+ const origem = campo.nome.toLowerCase();
332
+ if (origem === "ts" || origem === "typescript") {
333
+ implementacoes.push({ origem: "ts", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
334
+ continue;
335
+ }
336
+ if (origem === "py" || origem === "python") {
337
+ implementacoes.push({ origem: "py", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
338
+ continue;
339
+ }
340
+ if (origem === "dart") {
341
+ implementacoes.push({ origem: "dart", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
342
+ continue;
343
+ }
344
+ if (origem === "lua") {
345
+ implementacoes.push({ origem: "lua", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
346
+ continue;
347
+ }
348
+ if (origem === "cs" || origem === "csharp" || origem === "dotnet") {
349
+ implementacoes.push({ origem: "cs", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
350
+ continue;
351
+ }
352
+ if (origem === "java") {
353
+ implementacoes.push({ origem: "java", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
354
+ continue;
355
+ }
356
+ if (origem === "go" || origem === "golang") {
357
+ implementacoes.push({ origem: "go", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
358
+ continue;
359
+ }
360
+ if (origem === "rust" || origem === "rs") {
361
+ implementacoes.push({ origem: "rust", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
362
+ continue;
363
+ }
364
+ if (origem === "cpp" || origem === "cxx" || origem === "cc" || origem === "c++") {
365
+ implementacoes.push({ origem: "cpp", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
366
+ }
367
+ }
368
+ return implementacoes;
369
+ }
370
+
371
+ function converterVinculos(bloco?: BlocoGenericoAst): IrVinculo[] {
372
+ if (!bloco) {
373
+ return [];
374
+ }
375
+
376
+ const campos = bloco.campos.map((campo) => {
377
+ const valor = valorCampoCompleto(campo) ?? "";
378
+ return {
379
+ tipo: campo.nome,
380
+ valor,
381
+ arquivo: campo.nome === "arquivo" ? valor : undefined,
382
+ simbolo: campo.nome === "simbolo" ? valor : undefined,
383
+ recurso: ["recurso", "tabela", "fila", "cache", "storage"].includes(campo.nome) ? valor : undefined,
384
+ superficie: ["superficie", "rota", "worker", "cron", "webhook", "evento", "policy", "fila", "cache", "storage"].includes(campo.nome) ? valor : undefined,
385
+ statusResolucao: "nao_verificado" as const,
386
+ };
387
+ });
388
+
389
+ const linhas = bloco.linhas.map((linha) => {
390
+ const [tipo, ...resto] = linha.conteudo.split(/\s+/);
391
+ const valor = resto.join(" ").trim();
392
+ return {
393
+ tipo: tipo ?? "desconhecido",
394
+ valor,
395
+ statusResolucao: "nao_verificado" as const,
396
+ };
397
+ }).filter((item) => item.valor);
398
+
399
+ const subblocos = bloco.blocos
400
+ .filter((item): item is BlocoGenericoAst => item.tipo === "bloco_generico")
401
+ .map((item) => ({
402
+ tipo: item.palavraChave === "desconhecido" ? (item.nome ?? "desconhecido") : item.palavraChave,
403
+ valor: item.nome ?? item.palavraChave,
404
+ arquivo: valorCampoCompleto(localizarCampo(item, "arquivo")),
405
+ simbolo: valorCampoCompleto(localizarCampo(item, "simbolo")),
406
+ recurso: valorCampoCompleto(localizarCampo(item, "recurso", "tabela", "fila", "cache", "storage")),
407
+ superficie: valorCampoCompleto(localizarCampo(item, "superficie", "rota", "worker", "cron", "webhook", "evento")),
408
+ statusResolucao: "nao_verificado" as const,
409
+ }));
410
+
411
+ return [...campos, ...linhas, ...subblocos];
412
+ }
413
+
414
+ function converterExecucao(bloco?: BlocoGenericoAst): IrExecucao {
415
+ const idempotencia = valorCampoCompleto(localizarCampo(bloco, "idempotencia"));
416
+ const criticidadeOperacional = valorCampoCompleto(localizarCampo(bloco, "criticidade_operacional"));
417
+
418
+ return {
419
+ idempotencia: idempotencia === "verdadeiro" || idempotencia === "true",
420
+ timeout: valorCampoCompleto(localizarCampo(bloco, "timeout")) ?? "padrao",
421
+ retry: valorCampoCompleto(localizarCampo(bloco, "retry")) ?? "nenhum",
422
+ compensacao: valorCampoCompleto(localizarCampo(bloco, "compensacao")) ?? "nenhuma",
423
+ criticidadeOperacional: (
424
+ criticidadeOperacional === "baixa"
425
+ || criticidadeOperacional === "alta"
426
+ || criticidadeOperacional === "critica"
427
+ ) ? criticidadeOperacional : "media",
428
+ explicita: Boolean(bloco),
429
+ };
430
+ }
431
+
432
+ function converterAuth(bloco?: BlocoGenericoAst): IrAuth {
433
+ return extrairContratoAuth(bloco);
434
+ }
435
+
436
+ function converterAuthz(bloco?: BlocoGenericoAst): IrAuthz {
437
+ return extrairContratoAuthz(bloco);
438
+ }
439
+
440
+ function converterDados(bloco?: BlocoGenericoAst): IrDados {
441
+ return extrairContratoDados(bloco);
442
+ }
443
+
444
+ function converterAudit(bloco?: BlocoGenericoAst): IrAudit {
445
+ return extrairContratoAudit(bloco);
446
+ }
447
+
448
+ function converterSegredos(bloco?: BlocoGenericoAst): IrSegredos {
449
+ return extrairContratoSegredos(bloco);
450
+ }
451
+
452
+ function converterForbidden(bloco?: BlocoGenericoAst): IrForbidden {
453
+ return extrairContratoForbidden(bloco);
454
+ }
455
+
456
+ function converterErrosTask(bloco?: BlocoGenericoAst, fallback?: ErroSemanticoTask[]): IrErroOperacional[] {
457
+ const erros = new Map<string, IrErroOperacional>();
458
+
459
+ for (const campo of bloco?.campos ?? []) {
460
+ erros.set(campo.nome, {
461
+ codigo: campo.nome,
462
+ mensagem: valorCampoCompleto(campo) ?? "",
463
+ });
464
+ }
465
+
466
+ for (const subbloco of bloco?.blocos ?? []) {
467
+ if (subbloco.tipo !== "bloco_generico") {
468
+ continue;
469
+ }
470
+ const codigo = subbloco.nome ?? subbloco.palavraChave;
471
+ if (!codigo || codigo === "desconhecido") {
472
+ continue;
473
+ }
474
+ erros.set(codigo, {
475
+ codigo,
476
+ mensagem: valorCampoCompleto(localizarCampo(subbloco, "mensagem")) ?? `Erro estruturado "${codigo}".`,
477
+ categoria: valorCampoCompleto(localizarCampo(subbloco, "categoria")),
478
+ recuperabilidade: valorCampoCompleto(localizarCampo(subbloco, "recuperabilidade")),
479
+ acaoChamador: valorCampoCompleto(localizarCampo(subbloco, "acao_chamador")),
480
+ impactaEstado: valorCampoCompleto(localizarCampo(subbloco, "impacta_estado")) === "verdadeiro",
481
+ requerCompensacao: valorCampoCompleto(localizarCampo(subbloco, "requer_compensacao")) === "verdadeiro",
482
+ });
483
+ }
484
+
485
+ for (const erro of fallback ?? []) {
486
+ if (!erros.has(erro.codigo)) {
487
+ erros.set(erro.codigo, {
488
+ codigo: erro.codigo,
489
+ mensagem: erro.mensagem,
490
+ categoria: erro.categoria,
491
+ recuperabilidade: erro.recuperabilidade,
492
+ acaoChamador: erro.acaoChamador,
493
+ impactaEstado: erro.impactaEstado,
494
+ requerCompensacao: erro.requerCompensacao,
495
+ });
496
+ }
497
+ }
498
+
499
+ return [...erros.values()];
500
+ }
501
+
502
+ function extrairPerfil(bloco?: BlocoGenericoAst, padrao: PerfilCompatibilidade = "interno"): PerfilCompatibilidade {
503
+ const perfil = valorCampoCompleto(localizarCampo(bloco, "perfil", "compatibilidade"))?.toLowerCase();
504
+ if (
505
+ perfil === "publico"
506
+ || perfil === "interno"
507
+ || perfil === "experimental"
508
+ || perfil === "legado"
509
+ || perfil === "deprecado"
510
+ ) {
511
+ return perfil;
512
+ }
513
+ return padrao;
514
+ }
515
+
516
+ function tipoNaoPrimitivo(campo: IrCampo): string | undefined {
517
+ if (!TIPOS_PRIMITIVOS.has(campo.tipoBase)) {
518
+ return campo.tipoBase;
519
+ }
520
+ if (campo.tipoItem && !TIPOS_PRIMITIVOS.has(campo.tipoItem)) {
521
+ return campo.tipoItem;
522
+ }
523
+ if (campo.valorMapa && !TIPOS_PRIMITIVOS.has(campo.valorMapa)) {
524
+ return campo.valorMapa;
525
+ }
526
+ return undefined;
527
+ }
528
+
529
+ function deduplicarTexto(valores: string[]): string[] {
530
+ return [...new Set(valores.filter(Boolean))].sort((a, b) => a.localeCompare(b, "pt-BR"));
531
+ }
532
+
533
+ function resumirAgente(params: {
534
+ input?: IrCampo[];
535
+ output?: IrCampo[];
536
+ efeitos?: Array<{ categoria: string; alvo: string; criticidade?: string }>;
537
+ vinculos?: IrVinculo[];
538
+ execucao?: IrExecucao;
539
+ auth?: IrAuth;
540
+ authz?: IrAuthz;
541
+ dados?: IrDados;
542
+ audit?: IrAudit;
543
+ segredos?: IrSegredos;
544
+ forbidden?: IrForbidden;
545
+ superficiePublica?: string;
546
+ }): IrResumoAgente {
547
+ const entidadesAfetadas = deduplicarTexto([
548
+ ...(params.input ?? []).map(tipoNaoPrimitivo).filter((item): item is string => Boolean(item)),
549
+ ...(params.output ?? []).map(tipoNaoPrimitivo).filter((item): item is string => Boolean(item)),
550
+ ...(params.efeitos ?? []).map((efeito) => efeito.alvo),
551
+ ]);
552
+
553
+ const mutacoesPrevistas = deduplicarTexto(
554
+ (params.efeitos ?? []).map((efeito) => `${efeito.categoria}:${efeito.alvo}`),
555
+ );
556
+
557
+ const riscos = new Set<string>();
558
+ if ((params.efeitos ?? []).some((efeito) => efeito.categoria === "persistencia")) {
559
+ riscos.add("altera_persistencia");
560
+ }
561
+ if ((params.efeitos ?? []).some((efeito) => efeitoEhPrivilegiado(efeito))) {
562
+ riscos.add("efeito_privilegiado");
563
+ }
564
+ if ((params.efeitos ?? []).some((efeito) => efeito.criticidade === "alta" || efeito.criticidade === "critica")) {
565
+ riscos.add("efeito_critico");
566
+ }
567
+ if (params.execucao?.criticidadeOperacional === "alta" || params.execucao?.criticidadeOperacional === "critica") {
568
+ riscos.add("execucao_critica");
569
+ }
570
+ if (contratoDadosTemSensivel(params.dados)) {
571
+ riscos.add("dados_sensiveis");
572
+ }
573
+ if (params.segredos?.itens.length) {
574
+ riscos.add("segredo_operacional");
575
+ }
576
+ if ((params.vinculos ?? []).length === 0) {
577
+ riscos.add("vinculo_fraco");
578
+ }
579
+
580
+ const checks = new Set<string>();
581
+ checks.add("rodar sema validar --json");
582
+ if ((params.output ?? []).length > 0) {
583
+ checks.add("verificar guarantees");
584
+ }
585
+ if ((params.vinculos ?? []).length > 0) {
586
+ checks.add("rodar sema drift --json");
587
+ }
588
+ if (params.auth?.explicita || params.authz?.explicita) {
589
+ checks.add("revisar auth e authz");
590
+ }
591
+ if (params.dados?.explicita) {
592
+ checks.add("validar classificacao de dados");
593
+ }
594
+ if (params.audit?.explicita) {
595
+ checks.add("validar trilha de auditoria");
596
+ }
597
+ if (params.forbidden?.explicita) {
598
+ checks.add("confirmar proibicoes operacionais");
599
+ }
600
+ if (params.superficiePublica) {
601
+ checks.add("validar superficie publica impactada");
602
+ }
603
+
604
+ return {
605
+ riscos: [...riscos],
606
+ checks: [...checks],
607
+ entidadesAfetadas,
608
+ superficiesPublicas: params.superficiePublica ? [params.superficiePublica] : [],
609
+ mutacoesPrevistas,
610
+ };
611
+ }
612
+
613
+ function recomporCaminho(campo?: CampoAst): string | undefined {
614
+ const valor = valorCampoCompleto(campo);
615
+ return valor?.replace(/\s*\/\s*/g, "/").trim();
616
+ }
617
+
618
+ function ehUseInterop(
619
+ use: ModuloAst["uses"][number],
620
+ ): use is ModuloAst["uses"][number] & { origem: "ts" | "py" | "dart" | "lua" | "cs" | "java" | "go" | "rust" | "cpp" } {
621
+ return use.origem !== "sema";
622
+ }
623
+
624
+ function converterErroPublico(erro: IrErroOperacional, origemTask?: string) {
625
+ return {
626
+ nome: erro.codigo,
627
+ codigo: erro.codigo,
628
+ mensagem: erro.mensagem,
629
+ categoria: erro.categoria,
630
+ recuperabilidade: erro.recuperabilidade,
631
+ acaoChamador: erro.acaoChamador,
632
+ impactaEstado: erro.impactaEstado,
633
+ requerCompensacao: erro.requerCompensacao,
634
+ origemTask,
635
+ };
636
+ }
637
+
638
+ function calcularConfiancaPublica(route: IrRoute): NivelConfiancaSemantica {
639
+ if (route.task && route.vinculos.length > 0) {
640
+ return "alta";
641
+ }
642
+ if (route.task || route.vinculos.length > 0) {
643
+ return "media";
644
+ }
645
+ return "baixa";
646
+ }
647
+
648
+ function calcularRiscoPublico(route: IrRoute): NivelRiscoSemantico {
649
+ if (
650
+ !route.auth.explicita
651
+ || contratoDadosTemSensivel(route.dados)
652
+ || route.efeitosPublicos.some((efeito) => efeitoEhPrivilegiado(efeito) || efeito.categoria === "persistencia" || efeito.criticidade === "critica")
653
+ ) {
654
+ return "alto";
655
+ }
656
+ if (route.efeitosPublicos.length > 0 || route.errosPublicos.length > 0) {
657
+ return "medio";
658
+ }
659
+ return "baixo";
660
+ }
661
+
662
+ function converterSuperficie(
663
+ tipo: TipoSuperficieIr,
664
+ superficie: BlocoGenericoAst,
665
+ ): IrSuperficie {
666
+ const input = converterCampos(encontrarSubBloco(superficie, "input"));
667
+ const output = converterCampos(encontrarSubBloco(superficie, "output"));
668
+ const effects = (encontrarSubBloco(superficie, "effects")?.linhas ?? [])
669
+ .map((linha) => parsearEfeitoSemantico(linha.conteudo))
670
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha));
671
+ const vinculos = converterVinculos(encontrarSubBloco(superficie, "vinculos"));
672
+ const execucao = converterExecucao(encontrarSubBloco(superficie, "execucao"));
673
+ const auth = converterAuth(encontrarSubBloco(superficie, "auth"));
674
+ const authz = converterAuthz(encontrarSubBloco(superficie, "authz"));
675
+ const dados = converterDados(encontrarSubBloco(superficie, "dados"));
676
+ const audit = converterAudit(encontrarSubBloco(superficie, "audit"));
677
+ const segredos = converterSegredos(encontrarSubBloco(superficie, "segredos"));
678
+ const forbidden = converterForbidden(encontrarSubBloco(superficie, "forbidden"));
679
+ const task = valorCampoCompleto(localizarCampo(superficie, "task", "tarefa"));
680
+ const perfilCompatibilidade = extrairPerfil(superficie, tipo === "webhook" ? "publico" : "interno");
681
+ const resumoAgente = resumirAgente({
682
+ input,
683
+ output,
684
+ efeitos: effects,
685
+ vinculos,
686
+ execucao,
687
+ auth,
688
+ authz,
689
+ dados,
690
+ audit,
691
+ segredos,
692
+ forbidden,
693
+ superficiePublica: perfilCompatibilidade === "publico" ? `${tipo}:${superficie.nome ?? tipo}` : undefined,
694
+ });
695
+
696
+ return {
697
+ tipo,
698
+ nome: superficie.nome ?? tipo,
699
+ campos: converterCampos(superficie),
700
+ linhas: superficie.linhas.map((linha) => linha.conteudo),
701
+ task: task || undefined,
702
+ input,
703
+ output,
704
+ effects,
705
+ implementacoesExternas: converterImplementacoes(encontrarSubBloco(superficie, "impl")),
706
+ vinculos,
707
+ execucao,
708
+ auth,
709
+ authz,
710
+ dados,
711
+ audit,
712
+ segredos,
713
+ forbidden,
714
+ perfilCompatibilidade,
715
+ resumoAgente,
716
+ };
717
+ }
718
+
719
+ export function converterParaIr(modulo: ModuloAst, diagnosticos: Diagnostico[], contexto?: ContextoSemantico): IrModulo {
720
+ const perfilModulo = extrairPerfil(modulo.vinculos, modulo.routes.length > 0 || modulo.webhooks.length > 0 ? "publico" : "interno");
721
+
722
+ const types: IrType[] = modulo.types.map((type) => ({
723
+ nome: type.nome,
724
+ definicao: converterBloco(encontrarSubBloco(type.corpo, "fields") ?? type.corpo),
725
+ invariantes: (encontrarSubBloco(type.corpo, "invariants")?.linhas ?? [])
726
+ .map((linha) => parsearExpressaoSemantica(linha.conteudo))
727
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha)),
728
+ }));
729
+
730
+ const entities: IrEntity[] = modulo.entities.map((entity) => ({
731
+ nome: entity.nome,
732
+ campos: converterCampos(encontrarSubBloco(entity.corpo, "fields")),
733
+ invariantes: (encontrarSubBloco(entity.corpo, "invariants")?.linhas ?? [])
734
+ .map((linha) => parsearExpressaoSemantica(linha.conteudo))
735
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha)),
736
+ }));
737
+
738
+ const tarefasSemanticas = contexto?.tarefasDetalhadas ?? new Map();
739
+ const tasks: IrTask[] = modulo.tasks.map((task) => {
740
+ const input = converterCampos(task.input);
741
+ const output = converterCampos(task.output);
742
+ const effects = (task.effects?.linhas ?? [])
743
+ .map((linha) => parsearEfeitoSemantico(linha.conteudo))
744
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha));
745
+ const vinculos = converterVinculos(task.vinculos);
746
+ const execucao = converterExecucao(task.execucao);
747
+ const auth = converterAuth(encontrarSubBloco(task.corpo, "auth"));
748
+ const authz = converterAuthz(encontrarSubBloco(task.corpo, "authz"));
749
+ const dados = converterDados(encontrarSubBloco(task.corpo, "dados"));
750
+ const audit = converterAudit(encontrarSubBloco(task.corpo, "audit"));
751
+ const segredos = converterSegredos(encontrarSubBloco(task.corpo, "segredos"));
752
+ const forbidden = converterForbidden(encontrarSubBloco(task.corpo, "forbidden"));
753
+ const errosDetalhados = converterErrosTask(task.error, tarefasSemanticas.get(task.nome)?.errors);
754
+ const perfilCompatibilidade = extrairPerfil(task.corpo, "interno");
755
+ const resumoAgente = resumirAgente({
756
+ input,
757
+ output,
758
+ efeitos: effects,
759
+ vinculos,
760
+ execucao,
761
+ auth,
762
+ authz,
763
+ dados,
764
+ audit,
765
+ segredos,
766
+ forbidden,
767
+ });
768
+
769
+ return {
770
+ nome: task.nome,
771
+ input,
772
+ output,
773
+ rules: task.rules?.linhas.map((linha) => linha.conteudo) ?? [],
774
+ regrasEstruturadas: (task.rules?.linhas ?? [])
775
+ .map((linha) => parsearExpressaoSemantica(linha.conteudo))
776
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha)),
777
+ effects: task.effects?.linhas.map((linha) => linha.conteudo) ?? [],
778
+ efeitosEstruturados: effects,
779
+ implementacoesExternas: converterImplementacoes(task.impl),
780
+ vinculos,
781
+ execucao,
782
+ auth,
783
+ authz,
784
+ dados,
785
+ audit,
786
+ segredos,
787
+ forbidden,
788
+ guarantees: task.guarantees?.linhas.map((linha) => linha.conteudo) ?? [],
789
+ garantiasEstruturadas: (task.guarantees?.linhas ?? [])
790
+ .map((linha) => parsearExpressaoSemantica(linha.conteudo))
791
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha)),
792
+ errors: Object.fromEntries(errosDetalhados.map((erro) => [erro.codigo, erro.mensagem])),
793
+ errosDetalhados,
794
+ perfilCompatibilidade,
795
+ stateContract: task.state ? {
796
+ nomeEstado: task.state.nome ?? task.state.campos.find((campo) => campo.nome === "state" || campo.nome === "estado")?.valor,
797
+ campos: converterCampos(task.state),
798
+ linhas: task.state.linhas.map((linha) => linha.conteudo),
799
+ transicoes: (encontrarSubBloco(task.state, "transitions")?.linhas ?? task.state.linhas)
800
+ .map((linha) => parsearTransicaoEstado(linha.conteudo))
801
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha)),
802
+ } : undefined,
803
+ resumoAgente,
804
+ tests: (task.tests?.blocos.filter((bloco): bloco is BlocoCasoTesteAst => bloco.tipo === "caso_teste") ?? []).map(converterCaso),
805
+ };
806
+ });
807
+
808
+ const tarefasPorNome = new Map(tasks.map((task) => [task.nome, task] as const));
809
+
810
+ const flows: IrFlow[] = modulo.flows.map((flow) => {
811
+ const campos = converterCampos(flow.corpo);
812
+ const effects = (encontrarSubBloco(flow.corpo, "effects")?.linhas ?? [])
813
+ .map((linha) => parsearEfeitoSemantico(linha.conteudo))
814
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha));
815
+ const vinculos = converterVinculos(flow.vinculos);
816
+ const perfilCompatibilidade = extrairPerfil(flow.corpo, "interno");
817
+ return {
818
+ nome: flow.nome,
819
+ campos,
820
+ linhas: flow.corpo.linhas.map((linha) => linha.conteudo),
821
+ tasksReferenciadas: flow.corpo.campos
822
+ .filter((campo) => campo.nome === "task" || campo.nome === "tarefa")
823
+ .map((campo) => campo.valor),
824
+ etapasEstruturadas: flow.corpo.linhas
825
+ .map((linha) => parsearEtapaFlow(linha.conteudo))
826
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha)),
827
+ effects: (encontrarSubBloco(flow.corpo, "effects")?.linhas ?? []).map((linha) => linha.conteudo),
828
+ efeitosEstruturados: effects,
829
+ vinculos,
830
+ perfilCompatibilidade,
831
+ resumoAgente: resumirAgente({
832
+ input: campos,
833
+ efeitos: effects,
834
+ vinculos,
835
+ }),
836
+ };
837
+ });
838
+
839
+ const routes: IrRoute[] = modulo.routes.map((route) => ({
840
+ nome: route.nome,
841
+ campos: converterCampos(route.corpo),
842
+ linhas: route.corpo.linhas.map((linha) => linha.conteudo),
843
+ metodo: route.corpo.campos.find((campo) => campo.nome === "metodo")?.valor,
844
+ caminho: recomporCaminho(route.corpo.campos.find((campo) => campo.nome === "caminho")),
845
+ task: route.corpo.campos.find((campo) => campo.nome === "task" || campo.nome === "tarefa")?.valor,
846
+ inputPublico: [],
847
+ outputPublico: [],
848
+ errosPublicos: [],
849
+ efeitosPublicos: [],
850
+ vinculos: converterVinculos(route.vinculos),
851
+ auth: converterAuth(encontrarSubBloco(route.corpo, "auth")),
852
+ authz: converterAuthz(encontrarSubBloco(route.corpo, "authz")),
853
+ dados: converterDados(encontrarSubBloco(route.corpo, "dados")),
854
+ audit: converterAudit(encontrarSubBloco(route.corpo, "audit")),
855
+ segredos: converterSegredos(encontrarSubBloco(route.corpo, "segredos")),
856
+ forbidden: converterForbidden(encontrarSubBloco(route.corpo, "forbidden")),
857
+ perfilCompatibilidade: extrairPerfil(route.corpo, "publico"),
858
+ garantiasPublicasMinimas: [],
859
+ resumoAgente: {
860
+ riscos: [],
861
+ checks: [],
862
+ entidadesAfetadas: [],
863
+ superficiesPublicas: [],
864
+ mutacoesPrevistas: [],
865
+ },
866
+ publico: {
867
+ metodo: undefined,
868
+ caminho: undefined,
869
+ task: undefined,
870
+ input: [],
871
+ output: [],
872
+ errors: [],
873
+ effects: [],
874
+ garantiasMinimas: [],
875
+ },
876
+ })).map((route) => {
877
+ const routeAst = modulo.routes.find((item) => item.nome === route.nome)!;
878
+ const tarefaAssociada = route.task ? tarefasPorNome.get(route.task) : undefined;
879
+ const tarefaSemantica = route.task ? tarefasSemanticas.get(route.task) : undefined;
880
+ const inputPublicoDeclarado = converterCampos(encontrarSubBloco(routeAst.corpo, "input"));
881
+ const outputPublicoDeclarado = converterCampos(encontrarSubBloco(routeAst.corpo, "output"));
882
+ const errosDeclarados = converterErrosTask(encontrarSubBloco(routeAst.corpo, "error"), tarefaSemantica?.errors);
883
+ const efeitosPublicosDeclarados = (encontrarSubBloco(routeAst.corpo, "effects")?.linhas ?? [])
884
+ .map((linha) => parsearEfeitoSemantico(linha.conteudo))
885
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha));
886
+ const inputPublicoResolvido = inputPublicoDeclarado.length > 0
887
+ ? inputPublicoDeclarado
888
+ : (tarefaAssociada?.input ?? tarefaSemantica?.input?.map((campo: { nome: string; tipo: string; modificadores: string[] }) => ({
889
+ nome: campo.nome,
890
+ tipo: campo.tipo,
891
+ modificadores: campo.modificadores,
892
+ tipoOriginal: campo.tipo,
893
+ tipoBase: campo.tipo,
894
+ cardinalidade: "unitario" as const,
895
+ opcional: false,
896
+ tiposAlternativos: [],
897
+ refinamentos: [],
898
+ })) ?? []);
899
+ const outputPublicoResolvido = outputPublicoDeclarado.length > 0
900
+ ? outputPublicoDeclarado
901
+ : (tarefaAssociada?.output ?? tarefaSemantica?.output?.map((campo: { nome: string; tipo: string; modificadores: string[] }) => ({
902
+ nome: campo.nome,
903
+ tipo: campo.tipo,
904
+ modificadores: campo.modificadores,
905
+ tipoOriginal: campo.tipo,
906
+ tipoBase: campo.tipo,
907
+ cardinalidade: "unitario" as const,
908
+ opcional: false,
909
+ tiposAlternativos: [],
910
+ refinamentos: [],
911
+ })) ?? []);
912
+ const errosPublicosResolvidos = errosDeclarados.length > 0
913
+ ? errosDeclarados.map((erro) => converterErroPublico(erro, route.task))
914
+ : (tarefaAssociada?.errosDetalhados ?? (tarefaSemantica?.errors ?? []).map((erro: { codigo: string; mensagem: string }) => ({ codigo: erro.codigo, mensagem: erro.mensagem }))).map((erro: IrErroOperacional) =>
915
+ converterErroPublico(erro, route.task));
916
+ const garantiasPublicasMinimas = (tarefaAssociada?.guarantees ?? tarefaSemantica?.guarantees ?? []).filter((garantia: string) => {
917
+ const referencia = garantia.trim().split(/\s+/)[0] ?? "";
918
+ return outputPublicoResolvido.some((campo: IrCampo) => campo.nome === referencia || garantia.includes(`${campo.nome}.`));
919
+ });
920
+
921
+ const routeResolvida: IrRoute = {
922
+ ...route,
923
+ inputPublico: inputPublicoResolvido,
924
+ outputPublico: outputPublicoResolvido,
925
+ errosPublicos: errosPublicosResolvidos,
926
+ efeitosPublicos: efeitosPublicosDeclarados,
927
+ garantiasPublicasMinimas,
928
+ resumoAgente: resumirAgente({
929
+ input: inputPublicoResolvido,
930
+ output: outputPublicoResolvido,
931
+ efeitos: efeitosPublicosDeclarados,
932
+ vinculos: route.vinculos,
933
+ auth: route.auth,
934
+ authz: route.authz,
935
+ dados: route.dados,
936
+ audit: route.audit,
937
+ segredos: route.segredos,
938
+ forbidden: route.forbidden,
939
+ superficiePublica: `${route.metodo ?? "?"} ${route.caminho ?? "?"}`,
940
+ }),
941
+ publico: {
942
+ metodo: route.metodo,
943
+ caminho: route.caminho,
944
+ task: route.task,
945
+ input: inputPublicoResolvido,
946
+ output: outputPublicoResolvido,
947
+ errors: errosPublicosResolvidos,
948
+ effects: efeitosPublicosDeclarados,
949
+ garantiasMinimas: garantiasPublicasMinimas,
950
+ confiancaContrato: "media",
951
+ riscoRegressao: "medio",
952
+ divergenciasPublicas: [],
953
+ },
954
+ };
955
+
956
+ routeResolvida.publico.confiancaContrato = calcularConfiancaPublica(routeResolvida);
957
+ routeResolvida.publico.riscoRegressao = calcularRiscoPublico(routeResolvida);
958
+ return routeResolvida;
959
+ });
960
+
961
+ const superficies: IrSuperficie[] = [
962
+ ...modulo.workers.map((item) => converterSuperficie("worker", item)),
963
+ ...modulo.eventos.map((item) => converterSuperficie("evento", item)),
964
+ ...modulo.filas.map((item) => converterSuperficie("fila", item)),
965
+ ...modulo.crons.map((item) => converterSuperficie("cron", item)),
966
+ ...modulo.webhooks.map((item) => converterSuperficie("webhook", item)),
967
+ ...modulo.caches.map((item) => converterSuperficie("cache", item)),
968
+ ...modulo.storages.map((item) => converterSuperficie("storage", item)),
969
+ ...modulo.policies.map((item) => converterSuperficie("policy", item)),
970
+ ];
971
+
972
+ const states: IrState[] = modulo.states.map((state) => ({
973
+ nome: state.nome,
974
+ campos: converterCampos(encontrarSubBloco(state.corpo, "fields") ?? state.corpo),
975
+ linhas: state.corpo.linhas.map((linha) => linha.conteudo),
976
+ invariantes: (encontrarSubBloco(state.corpo, "invariants")?.linhas ?? [])
977
+ .map((linha) => parsearExpressaoSemantica(linha.conteudo))
978
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha)),
979
+ transicoes: (encontrarSubBloco(state.corpo, "transitions")?.linhas ?? [])
980
+ .map((linha) => parsearTransicaoEstado(linha.conteudo))
981
+ .filter((linha): linha is NonNullable<typeof linha> => Boolean(linha)),
982
+ }));
983
+
984
+ const databases = modulo.databases.map(converterDatabase);
985
+
986
+ const resumoAgenteModulo = resumirAgente({
987
+ input: [],
988
+ output: [],
989
+ efeitos: [
990
+ ...tasks.flatMap((task) => task.efeitosEstruturados),
991
+ ...routes.flatMap((route) => route.efeitosPublicos),
992
+ ...superficies.flatMap((superficie) => superficie.effects),
993
+ ],
994
+ vinculos: [
995
+ ...converterVinculos(modulo.vinculos),
996
+ ...tasks.flatMap((task) => task.vinculos),
997
+ ...routes.flatMap((route) => route.vinculos),
998
+ ...superficies.flatMap((superficie) => superficie.vinculos),
999
+ ],
1000
+ });
1001
+
1002
+ return {
1003
+ nome: modulo.nome,
1004
+ uses: contexto?.modulosImportados.length
1005
+ ? [...contexto.modulosImportados]
1006
+ : modulo.uses.filter((use) => use.origem === "sema").map((use) => use.caminho),
1007
+ imports: modulo.uses.map((use) => ({
1008
+ origem: use.origem,
1009
+ caminho: use.caminho,
1010
+ externo: use.origem !== "sema",
1011
+ })),
1012
+ interoperabilidades: contexto?.interoperabilidades.map((interop) => ({ ...interop })) ?? modulo.uses
1013
+ .filter(ehUseInterop)
1014
+ .map((use) => ({ origem: use.origem, caminho: use.caminho })),
1015
+ vinculos: converterVinculos(modulo.vinculos),
1016
+ perfilCompatibilidade: perfilModulo,
1017
+ types,
1018
+ entities,
1019
+ enums: modulo.enums.map((enumeracao) => ({ nome: enumeracao.nome, valores: enumeracao.valores })),
1020
+ tasks,
1021
+ flows,
1022
+ routes,
1023
+ superficies,
1024
+ states,
1025
+ databases,
1026
+ resumoAgente: {
1027
+ ...resumoAgenteModulo,
1028
+ superficiesPublicas: deduplicarTexto([
1029
+ ...routes.map((route) => `${route.metodo ?? "?"} ${route.caminho ?? route.nome}`),
1030
+ ...superficies
1031
+ .filter((superficie) => superficie.perfilCompatibilidade === "publico")
1032
+ .map((superficie) => `${superficie.tipo}:${superficie.nome}`),
1033
+ ]),
1034
+ },
1035
+ diagnosticos,
1036
+ };
1037
+ }