@semacode/cli 1.3.5 → 1.3.6

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